Tutorial :Hidden Features of C#? [closed]



Question:

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


Solution:1

I quite enjoy implicit generic parameters on functions. For example, if you have:

public void DoStuff<T>(T value);  

Instead of calling it like this:

DoStuff<int>(5);  

You can:

DoStuff(5);  

And it'll work out the generic type from the parameter's type.

  • This doesn't work if you're calling the method through reflection.
  • I remember having some weird problems on Mono.


Solution:2

Working with enums.

Convert a string to an Enum:

enum MyEnum  {      FirstValue,      SecondValue,      ThirdValue  }    string enumValueString = "FirstValue";  MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), enumValueString, true)  
  • I use this to load the value of CacheItemPriority in my ASP.NET applications from a settings table in a database so that I can control caching (along with other settings) dynamically without taking the application down.

When comparing variables of type enum, you don't have to cast to int:

MyEnum val = MyEnum.SecondValue;  if (val < MyEnum.ThirdValue)  {      // Do something  }  


Solution:3

To test if an IEnumerable<T> is empty with LINQ, use:

IEnumerable<T>.Any();

  • At first, I was using (IEnumerable<T>.Count() != 0)...
    • Which unnecessarily causes all items in the IEnumerable<T> to be enumerated.
  • As an improvement to this, I went on to use (IEnumerable<T>.FirstOrDefault() == null)...
    • Which is better...
  • But IEnumerable<T>.Any() is the most succinct and performs the best.


Solution:4

I'm pretty sure everyone is familiar with operator overloading, but maybe some aren't.

class myClass  {      private string myClassValue = "";        public myClass(string myString)      {          myClassValue = myString;      }        public override string ToString()      {          return myClassValue;      }        public static myClass operator <<(myClass mc, int shiftLen)      {          string newString = "";          for (int i = shiftLen; i < mc.myClassValue.Length; i++)              newString += mc.myClassValue[i].ToString();          mc.myClassValue = newString.ToString();          return mc;      }        public static myClass operator >>(myClass mc, int shiftLen)      {          char[] newString = new char[shiftLen + mc.myClassValue.Length];            for (int i = shiftLen; i < mc.myClassValue.Length; i++)              newString[i] += mc.myClassValue[i - shiftLen];            mc.myClassValue = new string(newString);          return mc;      }        public static myClass operator +(myClass mc, string args)      {          if (args.Trim().Length > 1)              mc.myClassValue += args;          return mc;      }        public static myClass operator -(myClass mc, string args)      {          if (args.Trim().Length > 1)          {              Regex rgx = new Regex(args);              mc.myClassValue = rgx.Replace(mc.myClassValue, "");          }          return mc;      }  }  

I think it's pretty cool to be able to shift a string left and right using << and >> or to remove a set of strings that follow a regular expression pattern using -=

myClass tmpClass = new myClass("  HelloWorld123");  tmpClass -= @"World";  tmpClass <<= 2;  Console.WriteLine(tmpClass);  


Solution:5

Instead of doing something cheesy like this:

Console.WriteLine("{0} item(s) found.", count);  

I use the following inline trick:

Console.WriteLine("{0} item{1} found.", count, count==1 ? "" : "s");  

This will display "item" when there's one item or "items" when there are more (or less) than 1. Not much effort for a little bit of professionalism.


Solution:6

Not a C# specific thing, but I am a ternary operations junkie.

Instead of

if (boolean Condition)  {      //Do Function  }  else  {      //Do something else  }  

you can use a succinct

booleanCondtion ? true operation : false operation;  

e.g.

Instead of

int value = param;  if (doubleValue)  {      value *= 2;  }  else  {      value *= 3;  }  

you can type

int value = param * (tripleValue ? 3 : 2);  

It does help write succinct code, but nesting the damn things can be nasty, and they can be used for evil, but I love the little suckers nonetheless


Solution:7

Expression to initialize a Dictionary in C# 3.5:

new Dictionary<string, Int64>() {{"Testing", 123}, {"Test", 125}};


Solution:8

You can switch on string!

switch(name)  {    case "Dave":      return true;    case "Bob":      return false;    default:      throw new ApplicationException();  }  

Very handy! and a lot cleaner than a bunch of if-else statements


Solution:9

C# allows you to add property setter methods to concrete types that implement readonly interface properties even though the interface declaration itself has no property setter. For example:

public interface IReadOnlyFoo  {     object SomeReadOnlyProperty { get; }  }  

The concrete class looks like this:

internal class Foo : IReadOnlyFoo  {     public object SomeReadOnlyProperty { get; internal set; }  }  

What's interesting about this is that the Foo class is immutable if you cast it to the IReadOnlyFoo interface:

// Create a Foo instance  Foo foo = new Foo();    // This statement is legal  foo.SomeReadOnlyProperty = 12345;    // Make Foo read only  IReadOnlyFoo readOnlyFoo = foo;    // This statement won't compile  readOnlyFoo.SomeReadOnlyProperty = 54321;  


Solution:10

Dictionary initializers are always useful for quick hacks and unit tests where you need to hardcode some data.

var dict = new Dictionary<int, string> { { 10, "Hello" }, { 20, "World" } };  


Solution:11

With LINQ it's possible to create new functions based on parameters. That's very nice if you have a tiny function which is exectued very often, but the parameters need some time to calculate.

    public Func<int> RandomGenerator      {          get          {              var r = new Random();              return () => { return r.Next(); };          }      }        void SomeFunction()      {          var result1 = RandomGenerator();            var x = RandomGenerator;          var result2 = x();      }  


Solution:12

Object.ReferenceEquals Method

Determines whether the specified Object instances are the same instance.

Parameters:

  • objA: System.Object - The first Object to compare.
  • objB: System.Object - The second Object to compare.

Example:

 object o = null;   object p = null;   object q = new Object();     Console.WriteLine(Object.ReferenceEquals(o, p));   p = q;   Console.WriteLine(Object.ReferenceEquals(p, q));   Console.WriteLine(Object.ReferenceEquals(o, p));  

Difference to "==" and ".Equals":

Basically, Equals() tests of object A has the same content as object B.

The method System.Object.ReferenceEquals() always compares references. Although a class can provide its own behavior for the equality operator (below), that re-defined operator isn't invoked if the operator is called via a reference to System.Object.

For strings there isn't really a difference, because both == and Equals have been overriden to compare the content of the string.

See also this answer to another question ("How do I check for nulls in an ‘==’ operator overload without infinite recursion?").


Solution:13

Explicit interface member implementation, wherein an interface member is implemented, but hidden unless the instance is cast to the interface type.


Solution:14

This isn't a C# specific type, but I just found the ISurrogateSelector and ISerializationSurrogate interfaces --

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.isurrogateselector.aspx

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.isurrogateselector.aspx

Using these in conjunction with the BinaryFormatter allows for non-serializable objects to be serialized via the implementation of a surrogate class. The surrogate pattern is well-understood in computer science, particularly when dealing with the problem of serialization. I think that this implementation is just tucked away as a parameter of the constructor to BinaryFormatter, and that's too bad.

Still - VERY hidden. :)


Solution:15

dynamic keyword in C# 4.0

You can use dynamic keyword, if you want your method calls to be resolved only at the runtime.

dynamic invoker=new DynamicInvoker();  dynamic result1=invoker.MyMethod1();  dynamic result2=invoker.MyMethod2();  

Here I'm implementing a dynamic invoker.

public class DynamicInvoker : IDynamicObject      {          public MetaObject GetMetaObject                (System.Linq.Expressions.Expression parameter)          {              return new DynamicReaderDispatch (parameter);          }      }        public class DynamicDispatcher : MetaObject      {          public DynamicDispatcher (Expression parameter)                      : base(parameter, Restrictions.Empty){ }            public override MetaObject Call(CallAction action, MetaObject[] args)          {              //You'll get MyMethod1 and MyMethod2 here (and what ever you call)              Console.WriteLine("Logic to invoke Method '{0}'", action.Name);              return this; //Return a meta object          }      }  


Solution:16

You can have generic methods in a non-generic class.


Solution:17

Here's one I discovered recently which has been useful:

Microsoft.VisualBasic.Logging.FileLogTraceListener  

MSDN Link

This is a TraceListener implementation which has a lot of features, such as automatic log file roll over, which I previously would use a custom logging framework for. The nice thing is that it is a core part of .NET and is integrated with the Trace framework, so its easy to pick up and use immediately.

This is "hidden" because its in the Microsoft.VisualBasic assembly... but you can use it from C# as well.


Solution:18

The usage of the default keyword in generic code to return the default value for a type.

public class GenericList<T>  {      private class Node      {          //...            public Node Next;          public T Data;      }        private Node head;        //...        public T GetNext()      {          T temp = default(T);            Node current = head;          if (current != null)          {              temp = current.Data;              current = current.Next;          }          return temp;      }  }  

Another example here


Solution:19

The built-in (2.0) MethodInvoker delegate is useful when you want to Invoke/BeginInvoke inline code. This avoids needing to create an actual delegate and separate method.

    void FileMessageEvent(object sender, MessageEventArgs e)      {            if (this.InvokeRequired == true)          {              this.BeginInvoke((MethodInvoker)delegate {                        lblMessage.Text=e.Message;                        Application.DoEvents();                    }              );             }      }  

Resolves the error: "Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type".


Solution:20

Array initialization without specifying the array element type:

var pets = new[] { "Cat", "Dog", "Bird" };  


Solution:21

Properties to display when viewing components Properties in design view:

private double _Zoom = 1;    [Category("View")]  [Description("The Current Zoom Level")]  public double Zoom  {  get { return _Zoom;}  set { _Zoom = value;}  }  

Makes things a lot easier for other users of your component libraries.


Solution:22

[field: NonSerialized]  public event EventHandler Event;  

This way, the event listener is not serialized.

Just [NonSerialized] does not work, because NonSerializedAttribute can only be applied to fields.


Solution:23

Cool trick to emulate functional "wildcard" arguments (like '_' in Haskell) when using lambdas:

(_, b, __) => b.DoStuff();  // only interested in b here  


Solution:24

Four switch oddities by Eric Lippert


Solution:25

The ability to use LINQ to do inline work on collections that used to take iteration and conditionals can be incredibly valuable. It's worth learning how all the LINQ extension methods can help make your code much more compact and maintainable.


Solution:26

You can create delegates from extension methods as if they were regular methods, currying the this parameter. For example,

static class FunnyExtension {      public static string Double(this string str) { return str + str; }      public static int Double(this int num) { return num + num; }  }      Func<string> aaMaker = "a".Double;  Func<string, string> doubler = FunnyExtension.Double;    Console.WriteLine(aaMaker());       //Prints "aa"  Console.WriteLine(doubler("b"));    //Prints "bb"  

Note that this won't work on extension methods that extend a value type; see this question.


Solution:27

Advanced Debugging

Display

The already mentioned attributes DebuggerDisplay and DebuggerBrowsable control the visibility of elements and the textual value displayed. Simply overriding ToString() will cause the debugger to use the output of that method.

If you want more complex output you can use/create a Debugger Visualizer, several examples are available here.

Son Of Strike

Microsoft provide a debugger extension known as SOS. This is an extremely powerful (though often confusing) extension which is an excellent way to diagnose 'leaks', more accurately unwanted references to objects no longer required.

Symbol Server for framework source

Following these instructions will allow you to step through the source of some parts of the framework.

Changes in 2010

Several enhancements and new features exist in Visual Studio 2010:


Solution:28

I don't think someone has mentioned that appending ? after a value type name will make it nullable.

You can do:

DateTime? date = null;  

DateTime is a structure.


Solution:29

HttpContext.Current.Server.Execute   

is great for rendering HTML to strings for AJAX callbacks. You can use this with a component instead of piecing together HTML string snippets. I was able to cut page bloat down a couple of hundred KB with virtually no mess. I used it like this:

Page pageHolder = new Page();  UserControl viewControl = (UserControl)pageHolder.LoadControl(@"MyComponent.ascx");  pageHolder.Controls.Add(viewControl);  StringWriter output = new StringWriter();  HttpContext.Current.Server.Execute(pageHolder, output, false);  return output.ToString();  


Solution:30

I like

#if DEBUG             //Code run in debugging mode    #else             //Code run in release mode    





        
Previous
Next Post »