Sie sind auf Seite 1von 3

7 Little-Known C# Programming Tricks

1. Indexers can use params


You may be familiar with the regular indexer pattern x = something[a]. To implement it you use the
following:
public string this[string key] {
get { return internalDictionary[key]; }
}

Did you know that you can use params to allow x = something[a, b, c, d] ?
Here's an example:
public IEnumerable<string> this[params string[] keys] {
get { return keys.Select(key => internalDictionary[key]).AsEnumerable(); }
}

The interesting thing is that you can have both indexers in the same class side-by-side. If someone
passes an array or multiple args they get an IEnumerable back. However, make a call with a single arg
and they will get a single value back.

2. Strings defined multiple times in your code are folded into one
instance
It's commonly believed that the following line of code will create a coup of strings every time, however
it will not.
if (x == "" || x == "y")

C#, like many other languages, employs string interning. This means that every string your program
compiles with gets put into an in-memory list that is referenced at runtime.
You can use String.Intern to see if its currently in this list but bear in mind that doing
String.Intern(what) == what will always return true as you just defined another string in your
source. String.IsInterned(wh + at) == what will also return true thanks to compiler optimizations.
String.IsInterned(new string(new char[] { w,h,a,t }) == new string(new char[] { w,h,a,t })
will only return true if you have what elsewhere in your program or something else at runtime has
added it to the intern pool.
If you have classes that build up or retrieve regularly used strings at runtime consider using
String.Intern to add them to the pool. Bear in mind once in they are in the pool they stay there until the
program exists so use String.Intern carefully. The syntax is String.Intern(someClass.ToString())
Another caveat is that performing (object)Hi == (object)Hi will return true thanks to interning. Try
it in your debug intermediate window and it will be false since the debugger does not intern your
strings.

3. Exposing types as a less capable type doesnt prevent their use


as a real type
A great example of this is when internal lists are exposed as IEnumerable properties as in the
following:
private readonly List<string> internalStrings = new List<string>();
public IEnumerable<string> AllStrings { get { return internalStrings; }

You would think you wouldn't be able to modify internal strings, but that's not the case. Here's how:
((List<string>)x.AllStrings).Add("Hello");

Even AsEnumerable wont help as that is a LINQ method that does nothing. You can use AsReadOnly
which creates a wrapper around the list that throws an exception when you try to set anything. This is a
good pattern to use when doing similar things with your own classes if you need to expose a subset of
internal structures.

4. Variables in methods can be scoped with just braces


In Pascal you had to declare all the variables your function would use at the start of the function.
Thankfully today the declarations can live next to their assignment and use which prevents accidentally
using the variable before you intended to.
What it doesnt do is stop you using it after you intended. Given that for/if/while/using etc. all allow a
nested scope it should come as only mild surprise that you can declare variables within braces without
a keyword to achieve the same result:
private void MultipleScopes() {
{ var a = 1; Console.WriteLine(a); }
{ var b = 2; Console.WriteLine(a); }
}

Its almost useful as now the second copy-and-pasted code block doesnt compile but a much better
solution is to split your method into smaller ones using the extract method refactoring.

5. Enums can have extension methods


Extension methods provide a way to write methods for existing classes. Since enums are simply
classes it shouldnt be too surprising that you can extend them like so:
enum Duration { Day, Week, Month };

static class DurationExtensions {


public static DateTime From(this Duration duration, DateTime dateTime) {
switch duration {
case Day: return dateTime.AddDays(1);
case Week: return dateTime.AddDays(7);
case Month: return dateTime.AddMonths(1);
default: throw new ArgumentOutOfRangeException("duration")
}
}
}

6. Order of static variable declaration in your source code


matters
Some people insist that variables are ordered alphabetically and there are tools around that can reorder
for you however there is one scenario where reordering can break your application.
static class Program {
private static int a = 5;
private static int b = a;

static void Main(string[] args) {


Console.WriteLine(b);
}
}

This will print the value 5. Reorder the a and b declarations and it will output 0.

7. Private instance variables of a class can be accessed by other


instances
You might think the following code won't work:
class KeepSecret {
private int someSecret;
public bool Equals(KeepSecret other) {
return other.someSecret == someSecret;
}
}

Its easy to think of private as meaning only this instance of a class can access them, but the reality is
that it means only this class can access it, including other instances of this class. This can be quite
useful for some comparison methods.

Das könnte Ihnen auch gefallen