Top c# Questions

List of Tags
1480
Serhat Özgel

This came to my mind after I learned the following from this question:

where T : struct

We, C# developers, all know the basics of C#. I mean declarations, conditionals, loops, operators, etc.

Some of us even mastered the stuff like Generics, anonymous types, lambdas, LINQ, ...

But what are the most hidden features or tricks of C# that even C# fans, addicts, experts barely know?

Here are the revealed features so far:


Keywords

Attributes

Syntax

Language Features

Visual Studio Features

Framework

Methods and Properties

Tips & Tricks

  • Nice method for event handlers by Andreas H.R. Nilsson
  • Uppercase comparisons by John
  • Access anonymous types without reflection by dp
  • A quick way to lazily instantiate collection properties by Will
  • JavaScript-like anonymous inline-functions by roosteronacid

Other

Answered By: ageektrapped ( 755)

This isn't C# per se, but I haven't seen anyone who really uses System.IO.Path.Combine() to the extent that they should. In fact, the whole Path class is really useful, but no one uses it!

I'm willing to bet that every production app has the following code, even though it shouldn't:

string path = dir + "\\" + fileName;
732
Lance Fisher

In C#, what is the difference between String and string? (note the case)

Example:

string s = "Hello, World";

String S = "Hello, World";

Also, what are the guidelines for the use of each?

Answered By: Derek Park ( 719)

string is an alias for System.String. So technically, there is no difference. It's like int vs. System.Int32.

As far as guidelines, I think it's generally recommended to use string any time you're referring to an object. e.g.

string place = "world";

Likewise, I think it's generally recommended to use String if you need to refer specifically to the class. e.g.

string greet = String.Format("Hello {0}!", place);

This is the style that Microsoft tends to use in their examples.


It appears that the guidance in this area may have changed, as StyleCop now enforces the use of the C#-specific aliases.

730
Ian Boyd

How can you enumerate a enum in C#?

e.g. the following does not compile:

public enum Suit
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod()
{
    foreach (Suit suit in Suit)
    {
        DoSomething(suit);
    }
}

It gives the compile time error:

'Suit' is a 'type' but is used like a 'variable'

It fails on the Suit keyword, the 2nd one.

Answered By: jop ( 1105)
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}
553
StriplingWarrior

When using lambda expressions or anonymous methods in C#, we have to be wary of the access to modified closure pitfall. For example:

foreach (var s in strings)
{
   query = query.Where(i => i.Prop == s); // access to modified closure

Due to the modified closure, the above code will cause all of the Where clauses on the query to be based on the final value of s.

As explained here, this happens because the s variable declared in foreach loop above is translated like this in the compiler:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...

... instead of like this:

while (enumerator.MoveNext())
{
   string s;
   s = enumerator.Current;

As pointed out here, there are no performance advantages to declaring a variable outside the loop, and under normal circumstances the only reason I can think of for doing this is if you plan to use the variable outside the scope of the loop:

} // end while
var finalString = s;

However, variables defined in a foreach loop cannot be used outside the loop:

foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.

So the compiler declares the variable in a way that makes it highly prone to an error that is often difficult to find and debug, while producing no perceivable benefits.

Is there something you can do with foreach loops this way that you couldn't if they were compiled with an inner-scoped variable, or is this just an arbitrary choice that was made before anonymous methods and lambda expressions were available or common, and which hasn't been revised since then?

Answered By: Eric Lippert ( 670)

The compiler declares the variable in a way that makes it highly prone to an error that is often difficult to find and debug, while producing no perceivable benefits.

Your criticism is entirely justified.

I discuss this problem in detail here:

Closing over the loop variable considered harmful

Is there something you can do with foreach loops this way that you couldn't if they were compiled with an inner-scoped variable? or is this just an arbitrary choice that was made before anonymous methods and lambda expressions were available or common, and which hasn't been revised since then?

The latter. The C# 1.0 specification actually did not say whether the loop variable was inside or outside the loop body, as it make no observable difference. When closure semantics were introduced in C# 2.0, the choice was made to put the loop variable outside the loop, consistent with the "for" loop.

I think it is fair to say that all regret that decision. This is one of the worst "gotchas" in C#, and we are going to take the breaking change to fix it. In C# 5 the foreach loop variable will be logically inside the body of the loop, and therefore closures will get a fresh copy every time.

The for loop will not be changed, and the change will not be "back ported" to previous versions of C#. You should therefore continue to be careful when using this idiom.

542
Jeff Atwood

Given a specific DateTime value, how do I display relative time, like

  • 2 hours ago
  • 3 days ago
  • a month ago

a la Ruby on Rail's time ago in words helper.

Answered By: Vincent Robert ( 396)

Jeff, your code is nice but could be clearer with constants (as suggested in Code Complete).

const int SECOND = 1;
const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;

if (delta < 0)
{
  return "not yet";
}
if (delta < 1 * MINUTE)
{
  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 2 * MINUTE)
{
  return "a minute ago";
}
if (delta < 45 * MINUTE)
{
  return ts.Minutes + " minutes ago";
}
if (delta < 90 * MINUTE)
{
  return "an hour ago";
}
if (delta < 24 * HOUR)
{
  return ts.Hours + " hours ago";
}
if (delta < 48 * HOUR)
{
  return "yesterday";
}
if (delta < 30 * DAY)
{
  return ts.Days + " days ago";
}
if (delta < 12 * MONTH)
{
  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
  return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
  return years <= 1 ? "one year ago" : years + " years ago";
}
533
Boris Callens

Is there a way to make the following return true?

string title = "ASTRINGTOTEST";
title.Contains("string");

There doesn't seem to be an overload that allows me to set the case sensitivity..
Currently I UPPERCASE them both, but that's just silly.

UPDATE
The sillyness I refer to is the i18n issues that come with up- and down casing.

Answered By: JaredPar ( 816)

You could use IndexOf() and pass StringComparison.OrdinalIgnoreCase

string title = "STRING";
bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;

Even better is defining a new extension method for string

public static bool Contains(this string source, string toCheck, StringComparison comp) {
  return source.IndexOf(toCheck, comp) >= 0;
}

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);
481
Jeff Atwood

Given a DateTime representing a person's birthday, how do I calculate their age?

Answered By: Mike Polen ( 511)

For some reason Jeff's code didn't seem simple enough. To me this seems simpler and easier to understand:

DateTime today = DateTime.Today;
int age = today.Year - bday.Year;
if (bday > today.AddYears(-age)) age--;
479
lomaxx

What's a quick and easy way to cast an int to an enum in C#?

Answered By: FlySwat ( 696)

From a string:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

From an int:

YourEnum foo = (YourEnum)yourInt;

Update : From number you can also:

YourEnum foo = Enum.ToObject(typeof(YourEnum) , yourInt);

Caution!

This ancient question is from the early days of Stack Overflow, and while we recognize its historical significance and have thus chosen to keep it around, please realize that if a question like this were to be asked today, it is very likely to be closed by the current community of users.

Please feel free to read and learn from the answers to this question, but refrain from asking similar questions just because this one exists.

Let's make a list of answers where you post your excellent and favorite extension methods.

The requirement is that the full code must be posted and a example and an explanation on how to use it.

Based on the high interest in this topic I have setup an Open Source Project called extensionoverflow on Codeplex.

Please mark your answers with an acceptance to put the code in the Codeplex project.

Please post the full sourcecode and not a link.

Codeplex News:

24.08.2010 The Codeplex page is now here: http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize / XmlDeserialize is now Implemented and Unit Tested.

11.11.2008 There is still room for more developers. ;-) Join NOW!

11.11.2008 Third contributer joined ExtensionOverflow, welcome to BKristensen

11.11.2008 FormatWith is now Implemented and Unit Tested.

09.11.2008 Second contributer joined ExtensionOverflow. welcome to chakrit.

09.11.2008 We need more developers. ;-)

09.11.2008 ThrowIfArgumentIsNull in now Implemented and Unit Tested on Codeplex.

Answered By: Winston Smith ( 232)
public static bool In<T>(this T source, params T[] list)
{
  if(null==source) throw new ArgumentNullException("source");
  return list.Contains(source);
}

Allows me to replace:

if(reallyLongIntegerVariableName == 1 || 
    reallyLongIntegerVariableName == 6 || 
    reallyLongIntegerVariableName == 9 || 
    reallyLongIntegerVariableName == 11)
{
  // do something....
}

and

if(reallyLongStringVariableName == "string1" || 
    reallyLongStringVariableName == "string2" || 
    reallyLongStringVariableName == "string3")
{
  // do something....
}

and

if(reallyLongMethodParameterName == SomeEnum.Value1 || 
    reallyLongMethodParameterName == SomeEnum.Value2 || 
    reallyLongMethodParameterName == SomeEnum.Value3 || 
    reallyLongMethodParameterName == SomeEnum.Value4)
{
  // do something....
}

With:

if(reallyLongIntegerVariableName.In(1,6,9,11))
{
      // do something....
}

and

if(reallyLongStringVariableName.In("string1","string2","string3"))
{
      // do something....
}

and

if(reallyLongMethodParameterName.In(SomeEnum.Value1, SomeEnum.Value2, SomeEnum.Value3, SomeEnum.Value4)
{
  // do something....
}
476
Paul Stovell

When building console applications that take parameters, you can use the arguments passed to Main(string[] args).

In the past I've simply indexed/looped that array and done a few regular expressions to extract the values. However, when the commands get more complicated, the parsing can get pretty ugly.

So I'm interested in:

  • Libraries that you use
  • Patterns that you use

Assume the commands always adhere to common standards such as answered here.

Answered By: jonp ( 235)

I would strongly suggest using NDesk.Options (Documentation) and/or Mono.Options (same API, different namespace). An example from the documentation:

bool show_help = false;
List<string> names = new List<string> ();
int repeat = 1;

var p = new OptionSet () {
    { "n|name=", "the {NAME} of someone to greet.",
       v => names.Add (v) },
    { "r|repeat=", 
       "the number of {TIMES} to repeat the greeting.\n" + 
          "this must be an integer.",
        (int v) => repeat = v },
    { "v", "increase debug message verbosity",
       v => { if (v != null) ++verbosity; } },
    { "h|help",  "show this message and exit", 
       v => show_help = v != null },
};

List<string> extra;
try {
    extra = p.Parse (args);
}
catch (OptionException e) {
    Console.Write ("greet: ");
    Console.WriteLine (e.Message);
    Console.WriteLine ("Try `greet --help' for more information.");
    return;
}