By Serhat Ozgel


2008-08-12 16:32:24 8 Comments

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

30 comments

@chakrit 2008-08-26 18:34:44

lambdas and type inference are underrated. Lambdas can have multiple statements and they double as a compatible delegate object automatically (just make sure the signature match) as in:

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

Note that I don't have a new CancellationEventHandler nor do I have to specify types of sender and e, they're inferable from the event. Which is why this is less cumbersome to writing the whole delegate (blah blah) which also requires you to specify types of parameters.

Lambdas don't need to return anything and type inference is extremely powerful in context like this.

And BTW, you can always return Lambdas that make Lambdas in the functional programming sense. For example, here's a lambda that makes a lambda that handles a Button.Click event:

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

Note the chaining: (dx, dy) => (sender, e) =>

Now that's why I'm happy to have taken the functional programming class :-)

Other than the pointers in C, I think it's the other fundamental thing you should learn :-)

@mgsloan 2008-08-18 23:08:35

Near all the cool ones have been mentioned. Not sure if this one's well known or not

C# property/field constructor initialization:

var foo = new Rectangle() 
{ 
    Fill = new SolidColorBrush(c), 
    Width = 20, 
    Height = 20 
};

This creates the rectangle, and sets the listed properties.

I've noticed something funny - you can have a comma at the end of the properties list, without it being a syntax error. So this is also valid:

var foo = new Rectangle() 
{ 
    Fill = new SolidColorBrush(c), 
    Width = 20, 
    Height = 20,
};

@OregonGhost 2009-03-30 11:07:52

The comma at the end makes fiddling with the values much easier :)

@Greg D 2009-05-08 16:59:44

The trailing comma is also useful for generated code. You'll note that it holds for many situations. I run across it most often when making an enum. :)

@John Bubriski 2009-06-08 16:27:15

Enums also support the trailing comma "feature".

@rball 2009-11-11 23:23:47

You don't need the () in Rectangle() either

@Christian Hubmann 2009-08-05 05:57:55

Conditional string.Format:

Applies different formatting to a number depending on whether the number is positive, negative, or zero.

string s = string.Format("{0:positive;negative;zero}", i);

e.g.

string format = "000;-#;(0)";

string pos = 1.ToString(format);     // 001
string neg = (-1).ToString(format);  // -1
string zer = 0.ToString(format);     // (0)

@tuinstoel 2009-08-05 17:25:14

This is similar to reg expressions, very useful, but I can't remember them either. I handle stuff like above with padleft and padright.

@Thomas Levesque 2009-08-23 11:18:40

Cool, I never knew it was possible... Is it documented anywhere ?

@devstuff 2009-08-23 11:55:56

@Thomas: It's documented in MSDN in the "The ";" Section Separator" section towards the end of the Custom Numeric Formatting topic at: msdn.microsoft.com/en-us/library/0c899ak8.aspx

@Laradda 2012-02-23 12:34:19

You can combine the protected and internal accessor to make it public within the same assembly, but protected in a diffrent assembly. This can be used on fields, properties, method and even constants.

@Pat Hermens 2008-08-18 00:10:35

I think if you have to use nullable types, it's better to use Nullable<.T> rather than the question mark notation. It makes it eye-achingly obvious that magic is occurring. Not sure why anyone would ever want to use Nullable<.bool> though.

In a VB.NET Web service where the parameter might not be passed through (because the partners request wasn't consistent or reliable), but had to pass validation against the proposed type (Boolean for "if is search request"). Chalk it up to "another demand by management"...

...and yes, I know some people think it's not the right way to do these things, but IsSearchRequest As Nullable(Of Boolean) saved me losing my mind that night!

@Dax70 2010-03-02 05:16:54

Most of the P/Invoke stuff is a bit strange.

Example of attributes:

[DllImport ("gdi32.dll")] 
[return : MarshalAs(UnmanagedType.I4)]
[StructLayout(LayoutKind.Sequential)]

@Keith 2008-08-12 18:23:40

Everything else, plus

1) implicit generics (why only on methods and not on classes?)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2) simple lambdas with one parameter:

x => x.ToString() //simplify so many calls

3) anonymous types and initialisers:

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

Another one:

4) Auto properties can have different scopes:

public int MyId { get; private set; }

Thanks @pzycoman for reminding me:

5) Namespace aliases (not that you're likely to need this particular distinction):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

@Adam Lassek 2008-09-18 16:42:54

I've actually needed to do the first one on a project using Anthem, because it clobbers the WebControls namespace.

@Echostorm 2008-10-07 14:08:57

in #3 you can do Enumerable.Range(1,5)

@Keith 2008-10-07 14:17:39

Yeah, you can for that specific example, maybe it was poorly chosen. You can init any array in this way: int[] arrayOfInt = new { 4, 8, 15, 16, 23, 42 }

@Lucas 2008-10-07 23:26:48

i think you've been able to initialize arrays with int[] nums = {1,2,3}; since 1.0 :) doesn't even need the "new" keyword

@Keith 2008-10-08 07:20:43

You can, but now you can also do this: var lst = new List<int> { 4, 8, 15, 16, 23, 42 }

@Pablo Retyk 2009-01-12 08:38:12

also lambda without parameters ()=> DoSomething();

@Chad Grant 2009-04-29 13:36:54

I weep for auto properties not getting default values

@Simon D. 2009-05-04 21:16:15

@3) int[] arrayOfInt = new { 1, 2, 3, 4, 5 }; I even more like var[] intArray=new {1,12,14}; @4) Unfortunately, only 'get;private set;' works, any other combination like 'get; internal set;' is not possible :O( Better than nothing but not perfectly consistent IMHO, though this is rather syntactical sugar and no fundamental language ability

@Keith 2009-05-04 21:23:16

I've used both { get; internal set; } and { get; protected set; }, so this pattern is consistent.

@Simon D. 2009-08-05 10:02:11

@Keith: +1 for this correction, I was mislead by someone stating this. In fact, one can chose various access modifiers for either get or set. The real restriction is that you cannot use one for get AND one for set (makes sense because then one should change the access modifier of the property instead of the accessors)

@Andrei Rînea 2009-09-02 07:57:09

The namespaces aliases remind me of the yucky c++ :-S

@BrokeMyLegBiking 2010-02-06 12:13:39

Ooo, I like this application of Enumerable.Range() which looks cleaner: new way:______________ foreach (int i in Enumerable.Range(1, 100)) { Console.WriteLine(i); } old way:_______________ for (int i = 1; i <= 100; i++) { Console.WriteLine(i); }

@Keith 2010-02-12 09:44:13

@BrokeMyLegBiking - actually I would keep the for loop in that case - the foreach would be slower and more confusing. The Enumerable.Range is most useful for initialising collections without a countered loop. If you're going to loop anyway it's best to stick with for

@Kirk Broadhurst 2010-03-05 23:59:13

or web.Control aWebControl = new web.Control();

@Keith 2010-03-08 11:32:08

@Kirk Broadhurst - you're right - new web.Control() would also work in this example. The :: syntax forces it to treat the prefix as a namespace alias, so you could have a class called web and the web::Control syntax would still work, while the web.Control syntax wouldn't know whether to check the class or the namespace. Because of that I tend to always use :: when doing namespace aliases.

@Stéphane 2010-04-22 07:52:12

this last namespace trick is really useful to override an existing one. See on my blog for example! alsagile.com/archive/2010/03/09/…

@L. Kolmodin 2010-05-13 10:45:04

You can have as many parameters to your lambdas as you'd like: (n1,n2,n3) => n1+n2+n3;

@Keith 2010-05-13 12:53:08

@L. Kolmodin - yeah you can - my 2nd point is that when you just have 1 you can skip the parameters: (x) => becomes x =>

@Lukasz Madon 2010-08-15 02:01:21

//Duck-typed: works with any .Add method. var colours = new Dictionary<string, string> { { "red", "#ff0000" }, { "green", "#00ff00" }, { "blue", "#0000ff" } }; int[] arrayOfInt = { 1, 2, 3, 4, 5 }; this is not duck typing!

@Keith 2010-08-16 10:18:43

@lukas - this is syntactic sugar, but under the hood it works on any class that implements a method like void Add(...) - that includes your own classes without the need to implement an interface. I agree that on the int[] it's C# syntax, but that it works for any type with an Add method is duck-typing

@FunctorSalad 2011-01-06 19:48:00

@"1) implicit generics (why only on methods and not on classes?)" -- this can be alleviated for constructor calls through wrapping the constructor like this: class C<A,B> { public C(A a, B b) { ... } } static class C { public C<A,B> New<A,B>(A a, B b) { return new C<A,B>(A a, B b); } class Main { public void main() { var c = C.New(someA,someB); // type params inferred }

@Keith 2011-01-07 09:11:12

@FunctorSalad - I know, which makes it even less logical that you can't, see my question on it: stackoverflow.com/questions/45604

@HuBeZa 2011-01-31 11:15:00

@Keith and @lukas: it is duck-typing but you also have to implement System.Collections.IEnumerable. You can get really crazy with void Add overload: new MyClass { 1, "a", { 1, "a" } };. See this question

@Keith 2011-01-31 13:49:18

@HuBeZa - good point, I guess that's because Add on its own could mean something else, so List<int> x = new List<int>{1, 2, 3, 4, 5 } should collection initialise and makes sense. However int has an Add method but int x = new int{1, 2, 3, 4, 5} makes no sense.

@Limited Atonement 2011-02-10 04:36:07

Number 3: But this doesn't work : byte[] get_bytes(){return {};}!!!

@Keith 2012-01-19 08:45:28

@LimitedAtonement sorry, it's a little confusing. The { syntax for add doesn't work when the collection is empty.

@Keith Adler 2009-09-16 19:38:58

You can limit the life and thus scope of variables by using { } brackets.

{
    string test2 = "3";
    Console.Write(test2);
}

Console.Write(test2); //compile error

test2 only lives within the brackets.

@ChrisF 2009-09-27 20:33:02

This is true of C++ too.

@Phillip Cloud 2012-01-08 21:46:51

True of any language with lexical scoping no?

@Kai 2012-01-30 10:30:25

hmmm...Is this a hidden feature??

@Ralph Caraveo 2009-04-15 00:23:53

Many people don't realize that they can compare strings using: OrdinalIgnoreCase instead of having to do someString.ToUpper(). This removes the additional string allocation overhead.

if( myString.ToUpper() == theirString.ToUpper() ){ ... }

becomes

if( myString.Equals( theirString, StringComparison.OrdinalIgnoreCase ) ){ ... }

@Robert Giesecke 2009-08-03 12:03:44

This could be changed quite easily to be null-safe as well: var isEqual = String.Equals(a, b, StringComparison.OrdinalIgnoreCase);

@Jeroen Landheer 2012-02-01 19:37:48

But... this isn't a C# feature, it is a feature of the .Net framework, more specifically a feature of the class "String"

@Nelson Miranda 2008-08-20 19:17:16

You type "prop" and then press [TAB] twice, it generates useful code for your properties and can speed your typing.

I know this works in VS 2005 (I use it) but I don´t know in previous versions.

@BlackTigerX 2008-09-16 19:55:38

this is a feature of the IDE

@Rob 2008-09-19 14:39:54

I think it's VS 2005 and up. I use it a lot :-)

@George Mauer 2009-01-05 19:25:25

Coderush shortens it to 'p' ;)

@LBugnion 2009-01-07 10:11:12

This is not a feature per se. It's a Visual Studio code snippet. You can create your own snippets, or even find some on internet. Check Dr WPF's code snippets, for example.

@Bhaskar 2009-07-01 08:49:38

ctor can be used to create a constructor

@Patrick 2012-02-28 16:33:18

Ctrl K, Ctrl X shows all the snippets available in Visual Studio.

@Shital Shah 2009-11-10 11:28:19

C# + CLR:

  1. Thread.MemoryBarrier: Most people wouldn't have used it and there is some inaccurate information on MSDN. But if you know intricacies then you can do nifty lock-free synchronization.

  2. volatile, Thread.VolatileRead, Thread.VolatileWrite: There are very very few people who gets the use of these and even fewer who understands all the risks they avoid and introduce :).

  3. ThreadStatic variables: There was only one situation in past few years I've found that ThreadStatic variables were absolutely god send and indispensable. When you want to do something for entire call chain, for example, they are very useful.

  4. fixed keyword: It's a hidden weapon when you want to make access to elements of large array almost as fast as C++ (by default C# enforces bound checks that slows down things).

  5. default(typeName) keyword can be used outside of generic class as well. It's useful to create empty copy of struct.

  6. One of the handy feature I use is DataRow[columnName].ToString() always returns non-null value. If value in database was NULL, you get empty string.

  7. Use Debugger object to break automatically when you want developer's attention even if s/he hasn't enabled automatic break on exception:


#if DEBUG  
    if (Debugger.IsAttached)  
        Debugger.Break();  
#endif
  1. You can alias complicated ugly looking generic types so you don't have to copy paste them again and again. Also you can make changes to that type in one place. For example,

    using ComplicatedDictionary = Dictionary<int, Dictionary<string, object>>;
    ComplicatedDictionary myDictionary = new ComplicatedDictionary();

@Cohen 2009-11-10 19:28:46

Sweet, great tips, in the last one you had tag trouble... replace < with &lt; and we will be able to read it :)

@sehe 2011-03-23 23:08:37

Now most of this comes down to 'people don't know the mechanics behind threading' IMHO. That may be true, but doesn't come close to 'hidden language features'? Thumbs up for Debugger.Break()

@Judah Gabriel Himango 2008-08-12 18:50:29

Here are some interesting hidden C# features, in the form of undocumented C# keywords:

__makeref

__reftype

__refvalue

__arglist

These are undocumented C# keywords (even Visual Studio recognizes them!) that were added to for a more efficient boxing/unboxing prior to generics. They work in coordination with the System.TypedReference struct.

There's also __arglist, which is used for variable length parameter lists.

One thing folks don't know much about is System.WeakReference -- a very useful class that keeps track of an object but still allows the garbage collector to collect it.

The most useful "hidden" feature would be the yield return keyword. It's not really hidden, but a lot of folks don't know about it. LINQ is built atop this; it allows for delay-executed queries by generating a state machine under the hood. Raymond Chen recently posted about the internal, gritty details.

@HuBeZa 2011-01-31 11:53:52

More details on the undocumented keywords by Peter Bromberg. I still don't get if there are reasons to ever use them.

@Judah Gabriel Himango 2011-01-31 19:14:28

@HuBeZa with the advent of generics, there aren't many (any?) good reasons to used __refType, __makeref, and __refvalue. These were used primarily to avoid boxing prior to generics in .NET 2.

@Matt Johnson-Pint 2011-11-10 14:50:09

How about a code example?

@Judah Gabriel Himango 2011-11-10 17:13:23

Matt, with the introduction of generics in .NET 2, there's little reason to use these keywords, as their purpose was to avoid boxing when dealing with value types. See the link by HuBeZa, and also see codeproject.com/Articles/38695/UnCommon-C-keywords-A-Look#ud

@Eyvind 2008-11-17 09:28:42

Regarding foreach: It does not use 'duck typing', as duck typing IMO refers to a runtime check. It uses structural type checking (as opposed to nominal) at compile time to check for the required method in the type.

@sehe 2011-03-24 00:32:44

yeah duck typing should be reserved for full dynamics IMHO too; however: foreach does use duck typing in that it will coerce .NET 1.1 (non-generic) GetEnumerator() iterators for you at runtime (this happens to be both a pitfall and the reason for Cast<> to be so convenient).

@ljs 2008-08-28 20:59:59

I like looking up stuff in a list like:-

bool basketContainsFruit(string fruit) {
  return new[] { "apple", "orange", "banana", "pear" }.Contains(fruit);
}

Rather than:-

bool basketContainsFruit(string fruit) {
  return fruit == "apple" || fruit == "orange" || fruit == "banana" ||
    fruit == "pear";
}

Doesn't come up that much in practice, but the idea of matching items against the subject of the search can be really quite useful + succinct.

@lc. 2008-12-13 16:34:09

I'm curious what the compiler spits out for both implementations. The first one definitely looks cleaner and is a cute way of doing it. Could be slower though if the object is actually created in memory first then iterated through.

@el2iot2 2009-01-26 01:14:40

you probably wanted fruit == banana?

@xanadont 2009-05-05 20:23:25

Kinda cool. But I would tweak it to use a static array so that it's not being newed every time the method is called.

@Arnis Lapsa 2009-06-06 19:55:34

Used InList in Visual Foxpro. Created lame static method which accepts params list just to reproduce the same. I'm glad there is a cleaner approach. :)

@codymanix 2009-09-12 19:35:06

You know that the first method every call a new array is created and that calling Contains is lots of slower than a few comparisons. But yes, it is convenient :)

@ljs 2009-09-12 21:58:22

@codymanix 0 yes, it's inefficient, but most of the time the inefficiency makes no difference to the perf of the application. Don't optimise unless the profiler says so :) - prefer readability over micro-perf issues unless the profiler disagrees :)

@P Daddy 2009-10-10 15:30:41

But you can have the best of both worlds (at least for this example, or for any integral type) using switch. Example follows, but readability suffers in comments due to lack of newlines: switch(fruit){ case "apple": case "orange": case "banana": case "pear": return true; default: return false; }

@Fowl 2010-06-26 11:40:40

except that in c# we don't have fallthrough

@ljs 2010-06-27 22:27:26

@P Daddy - true, but does suffer from a lot of additional syntax. @Fowl - you can have fallthrough if the cases have no code (until the fallen-through case of course).

@Michael 2010-09-07 11:49:04

@Fowl, yes we have, only for empty case statements, like this.

@John Gibb 2011-04-18 17:50:17

public static bool In<T>(T value, params T[] items){ return items.Contains(value); } if (fruit.In("apple", "orange", "banana", "pear")) { ... }

@Grigory 2011-08-03 11:29:30

This code creates new array each call. Actually it is incorrect when you create an new object when you really need to verify an argument. And please, dont tell me about readability. Semantically wrong syntax can not be readable. And short code/nicely put braces is not readability.

@ljs 2011-08-04 08:20:50

@Belorus I think you're treating it as if readability were a science, which it is not. Yes, it is a performance hit, but very often it will make no difference to the overall performance of the program. How is it 'wrong' if it does the job, even if it needlessly allocates memory? Readability is a very subjective thing - what seems simple to one person can seem appalling to another.

@Jan Slodicka 2012-02-29 11:52:39

For me this is a classic example of bad programming. Terrible performance, bad readability. (Yes, second statement is subjective.)

@Joel Coehoorn 2008-08-27 21:05:41

I'm late to this party, so my first choices are already taken. But I didn't see anyone mention this gem yet:

Parallel Extensions to the .NET Framework

It has things like replace with Parallel.For or foreach with Parallel.ForEach


Parallel Sample :
In your opinion, how many CLR object can be created in one second? enter image description here
See fallowing example :

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace ObjectInitSpeedTest
{
   class Program
   {
       //Note: don't forget to build it in Release mode.
       static void Main()
       {
           normalSpeedTest();           
           parallelSpeedTest();

           Console.ForegroundColor = ConsoleColor.White;
           Console.WriteLine("Press a key ...");
           Console.ReadKey();
       }

       private static void parallelSpeedTest()
       {
           Console.ForegroundColor = ConsoleColor.Yellow;
           Console.WriteLine("parallelSpeedTest");

           long totalObjectsCreated = 0;
           long totalElapsedTime = 0;

           var tasks = new List<Task>();
           var processorCount = Environment.ProcessorCount;

           Console.WriteLine("Running on {0} cores", processorCount);

           for (var t = 0; t < processorCount; t++)
           {
               tasks.Add(Task.Factory.StartNew(
               () =>
               {
                   const int reps = 1000000000;
                   var sp = Stopwatch.StartNew();
                   for (var j = 0; j < reps; ++j)
                   {
                       new object();
                   }
                   sp.Stop();

                   Interlocked.Add(ref totalObjectsCreated, reps);
                   Interlocked.Add(ref totalElapsedTime, sp.ElapsedMilliseconds);
               }
               ));
           }

           // let's complete all the tasks
           Task.WaitAll(tasks.ToArray());

           Console.WriteLine("Created {0:N} objects in 1 sec\n", (totalObjectsCreated / (totalElapsedTime / processorCount)) * 1000);
       }

       private static void normalSpeedTest()
       {
           Console.ForegroundColor = ConsoleColor.Green;
           Console.WriteLine("normalSpeedTest");

           const int reps = 1000000000;
           var sp = Stopwatch.StartNew();
           sp.Start();
           for (var j = 0; j < reps; ++j)
           {
               new object();
           }
           sp.Stop();

           Console.WriteLine("Created {0:N} objects in 1 sec\n", (reps / sp.ElapsedMilliseconds) * 1000);
       }
   }
}

@Morten Christiansen 2008-09-21 17:41:34

It is not really a language feature, though, as it is just a library which uses other language features cleverly.

@Surgical Coder 2008-08-15 11:34:02

My favourite is the

global::

keyword to escape namespace hell with some of our 3rd party code providers...

Example:

global::System.Collections.Generic.List<global::System.String> myList =
    new global::System.Collections.Generic.List<global::System.String>();

@Robin Maben 2010-12-13 09:17:50

It works just like an access specifier but with respect to namespaces i.e. global when used with the namespace alias qualifier :: refers to the global namespace, which is the default namespace for any C# program. Example usage here - msdn.microsoft.com/en-us/library/c3ay4x3d.aspx

@Benjol 2008-09-16 13:56:08

  1. I can't comment yet, but note that by default Visual Studio 2008 automatically steps over properties, so the DebuggerStepThrough attribute is no longer needed in that case.

  2. Also, I haven't noticed anyone showing how to declare a parameter-less lambda (useful for implementing Action<>)

    () => DoSomething(x);

You should also read up on closures - I'm not clever enough to explain them properly. But basically it means that the compiler does clever stuff so that the x in that line of code will still work even if it goes 'out of scope' after creating the lambda.

  1. I also discovered recently that you can pretend to ignore a lambda parameter:

    (e, _) => DoSomething(e)

It's not really ignoring it, it's just that _ is a valid identifier. So you couldn't ignore both of the parameters like that, but I think it is a kind of neat way to indicate that we don't care about that parameter (typically the EventArgs which is .Empty).

@Lars Mæhlum 2008-08-12 17:29:29

I have often come across the need to have a generic parameter-object persisted into the viewstate in a base class.

public abstract class BaseListControl<ListType,KeyType,ParameterType>
                 : UserControl 
                 where ListType : BaseListType
                 && ParameterType : BaseParameterType, new
{

    private const string viewStateFilterKey = "FilterKey";

    protected ParameterType Filters
    {
        get
        {
            if (ViewState[viewStateFilterKey] == null)
                ViewState[viewStateFilterKey]= new ParameterType();

            return ViewState[viewStateFilterKey] as ParameterType;
        }
        set
        {
            ViewState[viewStateFilterKey] = value;
        }
    }

}

Usage:

private void SomeEventHappened(object sender, EventArgs e)
{
    Filters.SomeValue = SomeControl.SelectedValue;
}

private void TimeToFetchSomeData()
{
    GridView.DataSource = Repository.GetList(Filters);
}

This little trick with the "where ParameterType : BaseParameterType, new" is what makes it really work.

With this property in my baseclass, I can automate handling of paging, setting filter values to filter a gridview, make sorting really easy, etc.

I am really just saying that generics can be an enormously powerful beast in the wrong hands.

@ilivewithian 2009-04-23 11:18:02

Maybe I'm being daft, but I'm not sure I understand the code. Could you post a more complete example?

@Lars Mæhlum 2009-04-23 14:22:51

Its pretty simple actually. If you have a GridView with a couple of DropDownLists to filter out content, you just put the values into your filter object that is persisted between postbacks, and send it as a parameter to the method that fetches data from the DB. You would just implement your UserControl inheriting from BaseListControl, and the base takes care of persisting "state" between postbacks.

@Andy Dent 2009-10-03 23:19:52

what do you mean "little trick"? Are you referring to the fact that you can't create a parameterised type inside a generic unless the generic constraints contains a "new" clause?

@Lars Mæhlum 2009-10-07 07:57:30

No, the little trick is constraining to BaseParameterType. A bit of a typo :\

@Nick Berardi 2008-08-12 16:38:50

Honestly the experts by the very definition should know this stuff. But to answer your question: Built-In Types Table (C# Reference)

The compiler flagging for numbers are widely known for these:

Decimal = M
Float = F
Double = D

// for example
double d = 30D;

However these are more obscure:

Long = L
Unsigned Long = UL
Unsigned Int = U

@OregonGhost 2009-03-30 10:56:24

Every time I'm dealing with decimals, I have to look up the m. Is it only me or is m not really intuitive? :)

@Nick Berardi 2009-03-30 19:46:11

The M syntax comes from the old VB type called Money. M == Money == Decimal.

@Maslow 2009-06-26 21:59:23

is there one for byte?

@Nick Berardi 2009-06-28 10:59:13

Nope, anything less than an Int32 is automatically inferred by the compiler based on the type to the left of it

@IAbstract 2010-01-28 06:24:07

@Nick: nice - I like learning the historicals behind the code.

@MBen 2011-05-23 16:40:24

@OregonGhost : and I guess the D was already taken :)

@odalet 2011-08-17 22:59:45

@Nick, Thanks for the history of m for decimal, this will help me remember this one. The one I never use is D for double; I always prefer writing 30.0 and curiously I regularly use the L for long.

@odalet 2011-08-17 23:03:55

It's interesting to note that though the lower case variants are valid, using l for long is discouraged because it can be easily mistaken for 1.

@goldenratio 2011-09-01 22:07:40

I remember M=Decimal/D=Double the same way I remember port/starboard: starboard means "Right" and has more "R"s. Decimal has an M but Double does not.

@TheSmurf 2008-08-12 16:37:19

Two of my personal favourites, which I see rarely used:

  1. Snippets (particularly for properties, which was made even better for Visual Studio 2008)
  2. The ObsoleteAttribute

@OregonGhost 2009-03-30 12:34:27

I like the switch snippet very much. Makes switching on an enum sooo much easier ;)

@Botz3000 2009-05-19 22:32:39

i regularly use a snippet for Properties calling OnPropertyChanged in the setter. very handy.

@maxwellb 2009-06-13 22:40:57

Are snippets though a feature of Visual Studio? Rather than C#/compiler?

@Maslow 2009-08-14 19:23:00

snippets are part of visual studio shortcut is ctrl - k+ctrl x

@murki 2009-10-15 22:24:24

better yet eg: write "for" or "switch" and then double-press 'tab' key

@devXen 2010-02-23 01:31:05

very handy indeed both with Ctrl-K + Ctrl-X and double tab on "for", "while", "foreach", "if", etc.

@David Clarke 2010-12-03 01:13:05

Yep, like obsolete for refactoring to highlight code I'm trying to make go away.

@Michael Stum 2008-08-12 16:34:44

"yield" would come to my mind. Some of the attributes like [DefaultValue()] are also among my favorites.

The "var" keyword is a bit more known, but that you can use it in .NET 2.0 applications as well (as long as you use the .NET 3.5 compiler and set it to output 2.0 code) does not seem to be known very well.

Edit: kokos, thanks for pointing out the ?? operator, that's indeed really useful. Since it's a bit hard to google for it (as ?? is just ignored), here is the MSDN documentation page for that operator: ?? Operator (C# Reference)

@Boris Callens 2008-11-08 01:18:27

The default value's documentation says it is not really setting the value of the property. It's only a helper for visualisers and code generators.

@Michael Stum 2010-01-10 01:32:53

As for DefaultValue: In the meantime, some libraries use it. ASP.net MVC uses DefaultValue on Parameters of a Controller Action (Which is very useful for non-nullable types). Strictly speaking of course, this is a code generator as the value is not set by the compiler but by MVC's code.

@Armstrongest 2010-03-29 18:23:41

The name for the ?? operator is the "Null Coalescing" operator

@BrainSlugs83 2012-02-28 21:05:27

yield is my favorite, the coalesce operator is up there though. I don't see anything about CAS, or assembly signing, strong names, the GAC... I suppose only CAS is C#... but so many developers have no clue about security.

@Dmitri Nesteruk 2008-10-26 19:04:33

Mixins. Basically, if you want to add a feature to several classes, but cannot use one base class for all of them, get each class to implement an interface (with no members). Then, write an extension method for the interface, i.e.

public static DeepCopy(this IPrototype p) { ... }

Of course, some clarity is sacrificed. But it works!

@John Bubriski 2009-06-08 16:23:56

Yeah I think this is the real power of extension methods. They basically allow for implementations of interface methods.

@Ryan Lundy 2010-03-05 22:28:18

This is also handy if you're using NHibernate (or Castle ActiveRecord) and you have to use interfaces for your collections. This way you can give behavior to the collection interfaces.

@WCWedin 2010-10-04 20:13:36

That's basically how all of the LINQ methods are implemented, for the record.

@Ryan Lundy 2011-03-23 22:34:13

Here's a link that talks about what I referred to above, using extension methods with collection interfaces in NHibernate or Castle ActiveRecord: devlicio.us/blogs/billy_mccafferty/archive/2008/09/03/…

@John Gibb 2011-04-18 17:40:03

If only they allowed extension properties!!!! I hated having to write an extension method that begged to be a read-only property....

@Mr.Mindor 2011-10-14 19:27:31

@John Gibb Read only property?: interface ISomething { string MyProp {get;} }

@MattDavey 2012-03-01 13:19:12

It's not strictly a mixin unless you can decorate a class with an interface after the fact - but still cool :)

@cllpse 2009-09-09 11:31:54

JavaScript-like anonymous inline-functions

Return a String:

var s = new Func<String>(() =>
{
    return "Hello World!";
})();

Return a more complex Object:

var d = new Func<Dictionary<Int32, String>>(() =>
{
    return new Dictionary<Int32, String>
    {
        { 0, "Foo" },
        { 1, "Bar" },
        { 2, "..." }
    };
})();

A real-world use-case:

var tr = new TableRow();

tr.Cells.AddRange
(
    new[]
    {
        new TableCell { Text = "" },
        new TableCell { Text = "" },
        new TableCell { Text = "" },

        new TableCell
        {
            Text = new Func<String>(() =>
            {
                return @"Result of a chunk of logic, without having to define
                         the logic outside of the TableCell constructor";
            })()
        },

        new TableCell { Text = "" },
        new TableCell { Text = "" }
    }
);

Note: You cannot re-use variable names inside the inline-function's scope.


Alternative syntax

// The one-liner
Func<Int32, Int32, String> Add = (a, b) => Convert.ToString(a + b);

// Multiple lines
Func<Int32, Int32, String> Add = (a, b) =>
{
    var i = a + b;

    return i.ToString();
};

// Without parameters
Func<String> Foo = () => "";

// Without parameters, multiple lines
Func<String> Foo = () =>
{
    return "";
};

Shorten a string and add horizontal ellipsis...

Func<String, String> Shorten = s => s.Length > 100 ? s.Substring(0, 100) + "&hellip;" : s;

@Hugoware 2009-01-02 16:26:32

I'd say using certain system classes for extension methods is very handy, for example System.Enum, you can do something like below...

[Flags]
public enum ErrorTypes : int {
    None = 0,
    MissingPassword = 1,
    MissingUsername = 2,
    PasswordIncorrect = 4
}

public static class EnumExtensions {

    public static T Append<T> (this System.Enum type, T value) where T : struct
    {
        return (T)(ValueType)(((int)(ValueType) type | (int)(ValueType) value));
    }

    public static T Remove<T> (this System.Enum type, T value) where T : struct
    {
        return (T)(ValueType)(((int)(ValueType)type & ~(int)(ValueType)value));
    }

    public static bool Has<T> (this System.Enum type, T value) where T : struct
    {
        return (((int)(ValueType)type & (int)(ValueType)value) == (int)(ValueType)value);
    }

}

...

//used like the following...

ErrorTypes error = ErrorTypes.None;
error = error.Append(ErrorTypes.MissingUsername);
error = error.Append(ErrorTypes.MissingPassword);
error = error.Remove(ErrorTypes.MissingUsername);

//then you can check using other methods
if (error.Has(ErrorTypes.MissingUsername)) {
    ...
}

This is just an example of course - the methods could use a little more work...

@devstuff 2009-08-23 12:16:56

Nice; but I'd use Include instead of Append since Append implies an order which the values may not have.

@Hugoware 2009-08-23 23:05:25

@devstuff - that is a good point, I didn't really ever think about it from that perspective.

@IAbstract 2010-01-28 06:44:11

@HBoss: I'm gonna use that. It will make it so much easier to implement Flags the way we should be.

@John Gibb 2011-04-18 18:13:07

Just figured something awesome out: All those "object" casts are causing a lot of boxing. If you add a generic constraint of where T : struct (so that T can't be a reference type), you can actually cast (int)(ValueType)value and avoid the boxing: I've edited the answer to show this.

@denis phillips 2008-08-17 01:01:28

Returning anonymous types from a method and accessing members without reflection.

// Useful? probably not.
private void foo()
{
    var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
    Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}

object GetUserTuple()
{
    return new { Name = "dp", Badges = 5 };
}    

// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
   return (T) obj;
}

@Jason Jackson 2008-09-30 01:10:47

That really doesn't get you anything. It is actually dangerous. What if GetUserTuple is modified to return multiple types? The cast will fail at run time. One of the great things about C#/.Net is the compile time checking. It would be much better to just create a new type.

@denis phillips 2008-09-30 14:41:53

@Jason I did say it's probably not useful but it is surprising (and I thought hidden).

@Paul Alexander 2009-05-07 09:05:20

While cool, this seems like a rather poor design choice. You've basically defined the anonymous type in two places. At that point, just declare a real struct and use it directly.

@George Mauer 2009-08-31 20:17:09

I could see this being useful if you have some sort of convention running throughout your application when you return tuples

@R. Martinho Fernandes 2009-11-13 11:58:05

@George: such a convention would be called a... struct?

@StriplingWarrior 2010-06-30 19:25:45

I think any potential use there may have been for this has probably been replaced by the dynamic keyword. If you're going to play with fire, you might was well do it the easy way. ;-)

@desco 2010-07-03 00:58:51

this trick is named 'cast by sample' and it will not work if method that returns anonymous type is located in another assembly.

@denis phillips 2010-07-03 02:24:54

@desco: "hidden features" not necessarily useful.

@kloffy 2010-07-04 20:31:52

@StriplingWarrior: Actually, anonymous types and dynamic go together quite well, so you cannot really say one replaces the other - if that is what you were suggesting. (i.e. with dynamic you could get rid of the cast entirely and just do dynamic user = GetUserTuple(); and the rest would stay the same...)

@StriplingWarrior 2010-07-06 17:32:59

@kloffy: yes, that's exactly what I mean. dynamic doesn't replace anonymous types: it replaces the need for this AnonCast method in order to access members without reflection.

@kloffy 2010-07-06 20:44:44

@StriplingWarrior: My bad, I misinterpreted your comment. I absolutely agree that the dynamic version is to be preferred (maybe it should be added to this answer as an alternative)...

@John Gibb 2011-04-18 17:35:00

weird. My co-worker and I actually wrote this exact function at a former job.... we had a (semi-)legitimate use case for it, but ended up just making a new type and removing the function before someone used it for evil ;)

@Florian Doyon 2009-10-26 16:45:31

I love abusing the fact that static templated classes don't share their static members.

Here's a threadsafe (at creation time) and cheap substitute to any Dictionary<Type,...> when the Type instance is known at compile-time.

public static class MyCachedData<T>{
    static readonly CachedData Value;
    static MyCachedData(){
       Value=// Heavy computation, such as baking IL code or doing lots of reflection on a type
    }
}

Cheers, Florian

@sehe 2011-03-23 23:14:46

a substitute to 'any Dictionary'? How? Care to explain?

@Florian Doyon 2011-03-24 15:13:41

hi, looks like my edit was cut... Should read "substitute to any dictionary taking a type as its key when the type is known at compile time" - fixed the original post (used backtick to escape brackets)

@devforall 2010-01-26 19:16:16

Another way of geting IEnumerable through yield without explicity creating an IEnumerable object

public IEnumerable<Request> SomeMethod(IEnumerable<Request> requests)
{
    foreach (Request request in requests)
       yield return DoSomthing(request);
}

@sehe 2011-03-23 22:56:23

of course the sample is weak, and it is hardly hidden. I'd prefer to write this as requests.Select(DoSomthing) 10 out of 10 times. (Also, edited the sample to fix code errors)

@Michael Prewecki 2008-09-03 15:03:20

TryParse method for each primitive type is great when validating user input.

double doubleValue
if (!Double.TryParse(myDataRow("myColumn"), out doubleValue))
{
    // set validation error
}

@Jeffrey L Whitledge 2008-09-19 15:36:42

I see I'm not the only one who forgets the "out" modifyer.

@Nicholas Mancuso 2008-09-25 18:06:23

doens't that return a bool? and set with an 'out' keyword?

@Mubashar 2010-02-11 10:37:59

I am bit late in this conversation and I would like to contribute the following. It may be a new thing for some developers.

public class User
{
    public long UserId { get; set; }
    public String Name { get; set; }
    public String Password { get; set; }
    public String Email { get; set; }
}

The usual way to declare and initialize it is with a constructor or like following.

User user = new User();
user.UserId = 1;
user.Name = "myname";
etc

But I learned following way to initialize it. I know Visual Basic developers will love it because it's like with operator available only in VB.NET and not in C# that is as follows.

User user = new User()
{
    UserId = 1,
    Name = "myname",
    Email = "[email protected]",
    Password = "mypassword"
};

@Konrad Rudolph 2010-02-11 10:41:28

Have a look at the answer right below yours – this has already been posted (more than once, I think).

@Mubashar 2010-02-12 09:01:15

:) Yes but its above my answer, but it wasn't in summary so i contributed.

@Avram 2010-02-13 19:52:07

csharp 3.5 contains this operator too, and you can use autoperties at examples

@chakrit 2010-02-25 08:20:50

this operator <> with operator ... With are wayyy more awesome :)

@Bryan 2008-09-09 14:04:46

A couple of things I like:

-If you create an interface similar to

 public interface SomeObject<T> where T : SomeObject<T>, new()

you force anything that inherits from this interface to contain a parameterless constructor. It is very useful for a couple of things I've run across.

-Using anonymous types to create a useful object on the fly:

var myAwesomeObject = new {Name="Foo", Size=10};

-Finally, many Java developers are familiar with syntax like:

public synchronized void MySynchronizedMethod(){}

However, in C# this is not valid syntax. The workaround is a method attribute:

 [MethodImpl(MethodImplOptions.Synchronized)]
 public void MySynchronizedMethod(){}

@Drew Noakes 2008-10-11 16:57:46

These are all good ideas. This site generally prefers one idea per answer so they can be rated individually. I would have given you three ratings :)

@Greg Dean 2008-10-13 03:34:12

[MethodImpl(MethodImplOptions.Synchronized)] = lock(this) = bad

@Matt Grande 2009-03-26 13:10:07

I'm not familiar with "Sychronized" method, can you tell me what they do?

@James Hart 2009-04-29 14:23:21

"you force anything that inherits from this interface to contain a parameterless constructor" Strictly speaking, no you don't - you force any class that implements your interface to prove that it know the name of a class that implements the interface and has a parameterless constructor. That's not the same thing. class A : SomeObject<A> { public A() // required } class B : SomeObject<A> { } // will compile fine, no constructor.

@Steven Evers 2009-09-03 05:46:23

@Matt, in this case, synchronised (or the methodimpl attribute) locks on the current object while the method is processing. However, the attribute causes a lock(this) while it does it: and in CLR via C# I recall that this was not a good idea (iirc, it exposed a potential security vulnerability but the book is all the way on the other side of the house, and it's really late). This is why most people will lock on a private object member variable instead of lock(this).

Related Questions

Sponsored Content

39 Answered Questions

26 Answered Questions

[SOLVED] Cast int to enum in C#

  • 2008-08-27 03:58:21
  • lomaxx
  • 1233155 View
  • 2939 Score
  • 26 Answer
  • Tags:   c# enums casting

26 Answered Questions

[SOLVED] How do I enumerate an enum in C#?

9 Answered Questions

[SOLVED] What are the correct version numbers for C#?

21 Answered Questions

[SOLVED] How do you give a C# Auto-Property a default value?

63 Answered Questions

[SOLVED] What is the difference between String and string in C#?

63 Answered Questions

[SOLVED] How do I calculate someone's age in C#?

  • 2008-07-31 23:40:59
  • Jeff Atwood
  • 558330 View
  • 1742 Score
  • 63 Answer
  • Tags:   c# .net datetime

10 Answered Questions

[SOLVED] Calling the base constructor in C#

191 Answered Questions

[SOLVED] Hidden features of Python

99 Answered Questions

[SOLVED] Hidden Features of JavaScript?

Sponsored Content