Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In C# generics, we can declare a constraint for a type parameter T to have a default constructor, by saying where T : new(). However, no other kinds of constraints like this are valid - new(string) for example, etc.

From a language design and/or implementation perspective, what is the reason for this?

Is there something in the way constructors work or in the way the type system is implemented that forbids this (or at least makes it harder)? If so, what is it? I recall reading somewhere that default(T) actually compiles to new T() for T : struct. Is it related to this, maybe?

Or is it simply a design decision made in order to avoid making the language too complicated?

share|improve this question
    
new(string) is not a default constructor constraint. Your question is tantamount to saying "Why aren't there constraints that require specific constructor signatures?" Very likely because such a constraint would not be particularly useful. –  Robert Harvey Apr 22 at 22:22
3  
@RobertHarvey Yes, it is exactly what I'm saying. I'm essentially asking whether there's something that makes default constructors special implementation-wise or if it was just an arbitrary choice to include this and not the other. –  Theodoros Chatzigiannakis Apr 22 at 22:27
    
Default constructors are useful in certain specific, and important, ways. For example, they make a type readily serializable. –  Robert Harvey Apr 22 at 22:30
3  
Specific ctor signatures could be useful. For example, if your type variable is constrained to be of Collection<T> with a ctor of T(Collection<T>), you know you can construct new collections given another. Whether that usefulness is worth the extra complexity, though, is a question. –  Phoshi Apr 23 at 8:20

2 Answers 2

up vote 2 down vote accepted

For an authoritative answer, I would refer you to Eric Lippert's answer to that question on StackOverflow a few years ago, a snippet of which is briefly quoted below.

However, in this specific case I can certainly give you some reasons why I would push back on the feature if it came up in a design meeting as a possible feature for a future version of the language.

...

I say that we should either do the whole feature or don't do it at all. If it is important to be able to restrict types to have particular constructors, then let's do the whole feature and restrict types on the basis of members in general and not just constructors.

share|improve this answer
    
That quote, taken out of context, is very misleading. It suggests that Eric thought that Microsoft should have "gone all the way," which is not his position at all. He is, in fact, squarely against the proposed feature. –  Robert Harvey Apr 22 at 22:29
1  
Thanks, this is does answer my question partially: Near the end of his answer, Eric Lippert mentions that it's a limitation of the IL and including this feature would require an addition to the IL. It'd be perfect if you could provide a source on what IL is generated for the part that is implemented - that is, generically calling a default constructor. –  Theodoros Chatzigiannakis Apr 22 at 22:33
    
@TheodorosChatzigiannakis: Why don't you fire up Telerik's Decompiler and find out for yourself? –  Robert Harvey Apr 22 at 22:37
2  
@RobertHarvey I don't think it suggests a position for him at all, but I've included an additional quote to emphasize his position. –  Chris Hannon Apr 22 at 22:37
1  
Hmm, F# has more advance ways to constrain a type, like checking as compile time if a class has an operator. Perhaps, F# needs a more powerful constraint system than C# due to its very strict type checking. Nonetheless, this language is able to implement a advanced ways to constain class on .Net Framework. –  OnesimusUnbound Apr 23 at 4:28

Decompiling (as per Robert Harvey's suggestion) yielded the following, for anyone interested. This method:

    static T GenericMake<T>()
        where T : new()
    {
        return new T();
    }

Apparently, when compiled, becomes this:

    private static T GenericMake<T>()
        where T : new()
    {
        T t;
        T t1 = default(T);
        if (t1 == null)
        {
            t = Activator.CreateInstance<T>();
        }
        else
        {
            t1 = default(T);
            t = t1;
        }
        return t;
    }

If T is a value type, new() becomes default(T).

If T is a reference type, new() works using reflection. Activator.CreateInstance() internally calls RuntimeType.CreateInstanceDefaultCtor().

So there it is - internally, default constructors really are special to the runtime. Giving other constructors the same treatment would have been costly, even if there are some valid use cases for more complicated constraints in generics.

share|improve this answer
2  
Interesting. Why the duplicate call to default(T) for value types? –  Avner Shahar-Kashtan Apr 23 at 11:51
1  
@AvnerShahar-Kashtan I don't know. It may be an artifact of the compilation/decompilation process, like the t variable (which could be replaced by nested return statements). –  Theodoros Chatzigiannakis Apr 23 at 12:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.