Why isn't this inferred automatically? - c#

Up until now, C# inferrence has always worked well for me. I have created a test example to simplify the case.
class Parent
{
public void InferrenceTesting<T>() where T : Parent
{
}
}
class Child : Parent
{
public void Test()
{
//this line gives me a compiler error : The type arguments for method 'Parent.InferrenceTesting<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
this.InferrenceTesting();
}
}
I have read quite a lot on inferrence, but I am clueless as of why this doesn't work.

Inference of generic method type arguments to the method type parameters proceeds by making inferences based on the relationships between the formal arguments and the formal parameters.
Your method has zero formal arguments and zero formal parameters, so no inferences are made.
Note that in particular inferences are never made from generic parameter constraints. Constraints are not part of the signature of a method and inference concerns itself with signatures. Rather, constraints are checked after type inference has succeeded. If you're expecting some sort of inference to be made from your where clause, your expectation is mistaken.
I have read quite a lot on inference, but I am clueless as of why this doesn't work.
You may wish to read my blog articles on type inference if this subject interests you. They may be more accurate than some of the other articles you've read on this subject; I occasionally see misinformation out there. From my current blog:
https://ericlippert.com/category/csharp/type-inference/
And my former Microsoft blog:
https://blogs.msdn.microsoft.com/ericlippert/tag/type-inference/
In particular, see
https://blogs.msdn.microsoft.com/ericlippert/2009/12/10/constraints-are-not-part-of-the-signature/
The comments to that blog are quite interesting. If you've ever wanted to see like a hundred people tell me that I'm wrong, the design is wrong, the implementation is wrong, well, that's the place to go.

There's nothing it can use to infer the type from. You've said that T has to be a type of Parent but since you're not passing a parameter of that type (which the compiler can use to infer the type) you'll have to explicitly name the type.

The compiler has no information to infer from - you need a parameter or some other information to tell the compiler what T should be in order to infer it.

I'm no expert in this, but I think there is nothing to infer from.
The simple fact that this method is declared in a Parent derivate has nothing to do with it.
You need an argument of type T for that method so that the compiler has something from which he can infere what should be used as T.
In your call, T does not need to be either Parent or Child. It can be anything as long as it inherits from Parent.

Related

Infer nesting generic type parameter [duplicate]

This question already has answers here:
Why must I provide explicitly generic parameter types While the compiler should infer the type?
(3 answers)
Closed 9 years ago.
I've noticed that the C# compiler doesn't infer second generic parameter.
Example:
C++ template code: (yea I know that templates don't work like generics)
class Test {
public:
template <class T,class V>
T test(V v) {
//do something with v
return T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //infers V as int
The templates (and generics) can't infer return type, so in C++ I give it the first template parameter, and the second template parameter is inferred from the variable type.
Now, same example in C#:
class Test {
public T test<T,V>(V v) where T: new() {
//do something with v
return new T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //Error Using the generic method 'Test.test<T,V>(V)' requires '2' type arguments
But if i use 1 type, I don't have to explicitly specify the type:
class Test {
public V test<V>(V v) where V: new() {
return new V();
}
};
int i = 0;
Test t = new Test();
int j = t.test(i); //OK infers V as int.
So, why can't C# generics infer the second type (while in c++ templates it clearly can) ?
I'm sure it's designed that way (I doubt they the .Net team overlooked this), so why is it designed this way that I must explicitly specify both types?
Edit:
From the discussions we had in the answers so far, both languages support overloading by number of template parameters.
So again, why is C# designed this way ? What's different in the language implementation that doesn't allow to explicitly declare only one parameter ?
C# has been designed to be a slightly less brain-bending language than C++.
In particular, I don't think it's a great idea to compare C# generics to C++ templates for various reasons - they're fundamentally two really quite different approaches to accomplishing similar things in some situations. The C++ approach is certainly flexible in some ways - although it doesn't allow (as I understand it) templates which only exist in binary form, or new template specializations to be created at execution time. Basically the C++ templating approach doesn't sit well with the rest of how .NET fits together.
Now as for why you can't specify some type arguments and allow others to be inferred (which is a language decision rather than a platform decision; I'm sure it would be feasible as far as .NET itself is concerned) - again, I believe this is for the sake of simplicity. Choosing the exact right method and the right type arguments is already extremely complicated in C# - more complicated than most C# developers can get their heads round. It involves:
Potentially considering methods up the type hierarchy from the compile-time type of the target
Overloading by number of parameters
Overloading by the number of type parameters
The effect of named arguments
The effect of optional parameters
The effect of generic type parameter constraints on parameter types (not constraints specified by the target method, note)
Method group to delegate conversions
Anonymous function conversions
Type inference for type arguments
Dynamic typing
Generic covariance and contravariance
Personally, I think that's enough to get my head around, without allowing yet more possiblities via "M can still be a candidate if it has at least as many type parameters as specified type arguments". Would you also want named type arguments and optional type parameters? ;)
I've looked at overloading quite a lot, following the spec thoroughly etc. I've found areas which make the language designers scratch their heads and try to work out what the compiler should do. I've found areas which the compiler definitely gets wrong. I wouldn't want to add any more complexity here without a really good reason.
So yes, it's basically for the sake of simplicity, and sometimes that's a pain - but often you can work around it. For every potential feature, you need to consider:
The benefit of the feature to end developers
The cost of the feature to end developers in terms of time spent understanding it
The cost to the language designers in designing and specifying it thoroughly
The cost to the compiler writers in implementing it correctly
The cost to the test team in testing it thoroughly (in conjunction with everything else around overloading)
The cost to future potential features (if this one makes the language more complicated, that leaves less "potentially grokable" additional complexity for other features)
As Dan said, C# doesn't allow you to infer only some type parameters of a generic parameter set. This is likely to enable overloading based on the number of generic parameters (which C# allows, at least for generic classes).
However, you can specify parameters of a generic class, and infer parameters of a generic method within that class. But this workaround isn't always a good solution.
One thing that can help in some cases where one would want to specify some type parameters and have others inferred is to create a generic static class with the parameters one wants to specify, and then within that class have a generic static method with the parameters one wants to have inferred. For example, I have a method which, given a method which is convertable to an Action(T,U,V), along with a T, will generate an Action(U,V) that will call that delegate with the originally-specified T along with the U and V. The method would be invoked as (vb syntax):
NewAction = ActionOf(Of FooType, BarType).NewAction(AddressOf MyFunctionOfBozFooBar, someBoz)
The compiler can determine one of the generic type parameters using the type of someBoz, even though it needs to have the FooType and BarType parameters explicitly specified.

Using a generic type argument in place of an argument of type System.Type. Is it a smell? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I often see (in many mocking libraries for example) methods where a generic type argument is used in place of an argument of type System.Type. I am specifically talking about cases where generic type is only being used in typeof(T) operation (i.e. no instance of type T is being used anywhere within the method, and T is not being used for either return type or other arguments).
For example consider following method:
public string GetTypeName(System.Type type) { return type.FullName; }
this method is often accompanied with a generic version:
public string GetTypeName<T>() { return GetTypeName(typeof(T)); }
Questions
is it a bad practice or a good practice?
Is this a syntactic sugar or are there more to it?
I see this as misusing a language feature to abbreviate a call to a method that accepts an argument of type System.Type
Would you consider this a smell? Should this be avoided? or is this actually a good practice (to provide a generic method as a shortcut to avoid typing typeof()).
Here are some practical issues with using this pattern I can think of:
if an argument of non System.Type type is added - method might need to be rewritten (if order of arguments is semantically significant) to non generic version (otherwise some arguments will be generic type arguments, and some will be regular arguments).
it requires two methods (generic and non generic for cases where type is not known at compile time). Consequently adds unit tests which are mostly meaningless.
On the other hand this is a common practice (and majority is always right, right?) but more importantly ReSharper prefers that signature when I do Extract Method refactoring on a code that requires single argument of type System.Type known at compile time (and I learned to take their recommendations though not on faith, but seriously).
I think you need to consider documentation. How obvious is it what the methods do? If you have two methods (one with Type and one with a type argument), users need to look at both and choose. People who aren't looking at your code may not realize that the second one simply calls the first.
Where it definitely makes sense to use both is when the type argument is actually used when it can be and there is some kind of fallback for the Type version. For example:
object GetThingOfType(Type type) { ... }
T GetThingOfType<T>() { return (T)GetThingOfType(typeof(T)); }
Another thing to consider: A type argument must always be written explicitly. If it is likely that there will be more than one operation to perform with the same type object, it's not helpful to use type arguments. Consider something like this:
var t = typeof(string);
var name = GetTypeName(t);
var assemblyName = t.Assembly.FullName;
Even though I know the type is string, I should not write GetTypeName<string> here because I would be repeating myself. By giving me an option that I would most often be better off not choosing, you're adding a bit of unnecessary complexity.
A more obscure point is IDE support of XML documentation. You document the type argument like this:
<typeparam name="T">important information</typeparam>
Then if you type GetTypeName< in C#, Visual Studio will show "T: important information". But, for some reason, when you type GetTypeName(Of in Visual Basic, it will not (as of 2012).
You are right: consider the semantics of the method. Is it operating on instances of the type, or on the type itself?
If it is operating on instances, then it should be a generic method. If it is on the type, then make it an argument of type Type.
So in your example I would say
public string GetTypeName(System.Type type) { return type.FullName; }
Whereas
public static int Count<TSource>(this IEnumerable<TSource> source)
Is operating on the instance source of type IEnumerable<TSource>.
In general, I have seen generics abused more than well-used. Any generic method implementation that does a typeof(T) or worse still, uses any kind of reflection is not really generic in my opinion and is an abuse. After all, generic means it works the same regardless of the type argument, doesn't it?
So, in summary, I agree with you - it smells.
I don't use the string GetName<T>() { return typeof(T).Name; } pattern as it is a misuse (misuse is probably strong but I can't think of the right word) of the design pattern that is the reason for generics, namely: generic type parameters are there for the compiler and the JITter (see the answer to this question) so that they can generate the type specific storage, parameters, stack variables, etc etc.
Using it as a convenient method for passing a type argument at runtime to me smells. There are times when typeof(T) is necessary, but I've found them to be rare and usually needed only when doing complex things with generics, as opposed to simple type safety sorts of things. If I see it, I definately pause and ask myself why it's there.
As it was already said, it looks to me like a matter of personal preferences. From my experience, most of the methods accepting an argument of type Type can be syntactically "sweetened" using an accompanying extension method.
So, in case of your example, I would make the second method an extension. Using this approach, you get a solution for your second concern - no unnecessary unit tests are required. The first one, however, remains; but then, addition of arguments will require refactoring anyway, so it will provide an opportunity to change the consumers of the extension method so they use the modified version of the original one.
Of course, it's just a personal opinion.
A generic method has an advantage over a method with a parameter of type Type, because it can reffer to other generic things using the provided type. This is particularly useful in the following scenario:
public string GetTypeName<T>()
{
return Cache<T>.TypeName;
}
private static class Cache<T>
{
public static readonly TypeName = GetTypeName(typeof(T));
}
This cache is easy, there is no need to mess around with dictionaries and it is automatically thread-safe.
This being said, if the implementation is not using this possibility, than the difference between the two is just cosmetic.
Methods that deal with types usually do just that: Dealing with types.
IMO, Class.Method<SomeType>(); is much better than Class.Method(typeof(SomeType));
But that is a matter of opinion I guess.
Consider LINQ's .OfType<T>(), for example:
personlist.OfType<Employee>().Where(x => x.EmployeeStatus == "Active");
versus:
personlist.OfType(typeof(Employee)).Where(x => ((Employee)x).EmployeeStatus == "Active");
which one would you prefer?

C# generics -- why do lambdas work, when simple methods don't?

I'm having trouble understanding why the C# compiler can infer types for
Array.ConvertAll(new int[1], i => Convert.ToDouble(i));
but not for
Array.ConvertAll(new int[1], Convert.ToDouble);
when it would seem that the former would be a more complicated deduction than the latter.
Could someone please explain why this happens?
This issue is pretty well covered in this (archived) blog post: http://blogs.msdn.com/b/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx
In summary as I understand it (should the link ever vanish); this was a conscious design decision in C# 3.0, in that it was not appropriate to perform type inference on Method Groups (your second example).
I guess quite a few folks didn't like that, so the issue was resolved for C# 4.0 (as of Visual Studio 2010);
"In C# 4.0, return type inference works on method group arguments when the method group can be associated unambiguously with a completely fixed set of argument types deduced from the delegate. Once the argument types associated with the method group are known, then overload resolution can determine unambiguously which method in the method group is the one associated with the delegate formal parameter; we can then make a return type inference from the specific method to the delegate return type."

Generics can't infer second parameter? [duplicate]

This question already has answers here:
Why must I provide explicitly generic parameter types While the compiler should infer the type?
(3 answers)
Closed 9 years ago.
I've noticed that the C# compiler doesn't infer second generic parameter.
Example:
C++ template code: (yea I know that templates don't work like generics)
class Test {
public:
template <class T,class V>
T test(V v) {
//do something with v
return T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //infers V as int
The templates (and generics) can't infer return type, so in C++ I give it the first template parameter, and the second template parameter is inferred from the variable type.
Now, same example in C#:
class Test {
public T test<T,V>(V v) where T: new() {
//do something with v
return new T();
}
};
int i = 0;
Test t = new Test();
double j = t.test<double>(i); //Error Using the generic method 'Test.test<T,V>(V)' requires '2' type arguments
But if i use 1 type, I don't have to explicitly specify the type:
class Test {
public V test<V>(V v) where V: new() {
return new V();
}
};
int i = 0;
Test t = new Test();
int j = t.test(i); //OK infers V as int.
So, why can't C# generics infer the second type (while in c++ templates it clearly can) ?
I'm sure it's designed that way (I doubt they the .Net team overlooked this), so why is it designed this way that I must explicitly specify both types?
Edit:
From the discussions we had in the answers so far, both languages support overloading by number of template parameters.
So again, why is C# designed this way ? What's different in the language implementation that doesn't allow to explicitly declare only one parameter ?
C# has been designed to be a slightly less brain-bending language than C++.
In particular, I don't think it's a great idea to compare C# generics to C++ templates for various reasons - they're fundamentally two really quite different approaches to accomplishing similar things in some situations. The C++ approach is certainly flexible in some ways - although it doesn't allow (as I understand it) templates which only exist in binary form, or new template specializations to be created at execution time. Basically the C++ templating approach doesn't sit well with the rest of how .NET fits together.
Now as for why you can't specify some type arguments and allow others to be inferred (which is a language decision rather than a platform decision; I'm sure it would be feasible as far as .NET itself is concerned) - again, I believe this is for the sake of simplicity. Choosing the exact right method and the right type arguments is already extremely complicated in C# - more complicated than most C# developers can get their heads round. It involves:
Potentially considering methods up the type hierarchy from the compile-time type of the target
Overloading by number of parameters
Overloading by the number of type parameters
The effect of named arguments
The effect of optional parameters
The effect of generic type parameter constraints on parameter types (not constraints specified by the target method, note)
Method group to delegate conversions
Anonymous function conversions
Type inference for type arguments
Dynamic typing
Generic covariance and contravariance
Personally, I think that's enough to get my head around, without allowing yet more possiblities via "M can still be a candidate if it has at least as many type parameters as specified type arguments". Would you also want named type arguments and optional type parameters? ;)
I've looked at overloading quite a lot, following the spec thoroughly etc. I've found areas which make the language designers scratch their heads and try to work out what the compiler should do. I've found areas which the compiler definitely gets wrong. I wouldn't want to add any more complexity here without a really good reason.
So yes, it's basically for the sake of simplicity, and sometimes that's a pain - but often you can work around it. For every potential feature, you need to consider:
The benefit of the feature to end developers
The cost of the feature to end developers in terms of time spent understanding it
The cost to the language designers in designing and specifying it thoroughly
The cost to the compiler writers in implementing it correctly
The cost to the test team in testing it thoroughly (in conjunction with everything else around overloading)
The cost to future potential features (if this one makes the language more complicated, that leaves less "potentially grokable" additional complexity for other features)
As Dan said, C# doesn't allow you to infer only some type parameters of a generic parameter set. This is likely to enable overloading based on the number of generic parameters (which C# allows, at least for generic classes).
However, you can specify parameters of a generic class, and infer parameters of a generic method within that class. But this workaround isn't always a good solution.
One thing that can help in some cases where one would want to specify some type parameters and have others inferred is to create a generic static class with the parameters one wants to specify, and then within that class have a generic static method with the parameters one wants to have inferred. For example, I have a method which, given a method which is convertable to an Action(T,U,V), along with a T, will generate an Action(U,V) that will call that delegate with the originally-specified T along with the U and V. The method would be invoked as (vb syntax):
NewAction = ActionOf(Of FooType, BarType).NewAction(AddressOf MyFunctionOfBozFooBar, someBoz)
The compiler can determine one of the generic type parameters using the type of someBoz, even though it needs to have the FooType and BarType parameters explicitly specified.

Type parameters vs. generics

Is there ever a reason to use Type parameters over generics, ie:
// this...
void Foo(Type T);
// ...over this.
void Foo<T>();
It seems to me that generics are far more useful in that they provide generic constraints and with C# 4.0, contravarience and covarience, as well as probably some other features I don't know about. It would seem to me that the generic form has all the pluses, and no negatives that the first doesn't also share. So, are there any cases where you'd use the first instead?
Absolutely: when you don't know the type until execution time. For example:
foreach (Type t in someAssembly.GetTypes())
{
Foo(t);
}
Doing that when Foo is generic is painful. It's doable but painful.
It also allows the parameter to be null, which can be helpful in some situations.
Well they really aren't the same at all.
With the second one, you've actually got a class of the compile-time type there (whatever has been passed in by whoever). So you can call specific functions on it (say if it's all of some given interface).
In your first example, you've got an object of class 'Type'. So you'll need to still determine what it is and do a cast to do anything useful with it.
Foo(someVariable.GetType()); // allowed
Foo<someVariable.GetType()>(); // illegal

Categories