Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't nested generic types be inferred?

Given the following classes...

public abstract class FooBase<TBar> where TBar : BarBase{}
public abstract class BarBase{}
public class Bar1 : BarBase{}
public class Foo1 : FooBase<Bar1> {}

...and the following method...

public TBar DoSomething<TFoo, TBar>(TFoo theFoo)
    where TFoo : FooBase<TBar>
    where TBar : BarBase
{
    return default(TBar);
}

Why can't the following line of code imply the return type?

Bar1 myBar = DoSomething(new Foo1());

Instead I have to specify the generic types like this...

Bar1 myBar = DoSomething<Foo1, Bar1>(new Foo1());
like image 698
Stefan Moser Avatar asked Jul 08 '11 21:07

Stefan Moser


People also ask

What are the constraints in generics?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.

Is generic type safe in C#?

Type Safety: Generic data types provide better type safety, especially in the case of collections. When using generics you need to define the type of objects to be passed to a collection. This helps the compiler to ensure that only those object types that are defined in the definition can be passed to the collection.

Can dynamic type be used for generic?

Not really. You need to use reflection, basically. Generics are really aimed at static typing rather than types only known at execution time.

Can generic be void?

Currently, void is not allowed as a generic parameter for a type or a method, what makes it hard in some cases to implement a common logic for a method, that's why we have Task and Task<T> for instance.


1 Answers

Method type inference ignores generic constraints on the method type parameters (*). Method type inference reasons only about deductions that can be made by comparing arguments to formal parameter types. Since the only generic type parameter that appears in your formal parameter types is TFoo, there is no way to deduce TBar.

Many people believe this design decision to be wrong, wrong, wrong. Though I take their point, this decision does lead to what are in my opinion some nice properties. For an extended debate on this issue, see the bazillion or so comments on this blog article telling me that I am wrong, wrong, wrong:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx


(*) Note that I said constraints on method type parameters are ignored, not constraints in general. If the deduced formal parameter types are constructed generic types such that the construction violates their type parameter constraints then this fact causes type inference to fail and the method is not a candidate for overload resolution. But under no circumstances do we make a deduction from a constraint other than "Hmm, clearly this is not going to work".

like image 51
Eric Lippert Avatar answered Sep 19 '22 19:09

Eric Lippert