The following program does not compile, because in the line with the error, the compiler chooses the method with a single T parameter as the resolution, which fails because the List<T> does not fit the generic constraints of a single T. The compiler does not recognize that there is another method that could be used. If I remove the single-T method, the compiler will correctly find the method for many objects.
I've read two blog posts about generic method resolution, one from JonSkeet here and another from Eric Lippert here, but I could not find an explanation or a way to solve my problem.
Obviously, having two methods with different names would work, but I like the fact that you have a single method for those cases.
namespace Test
{
using System.Collections.Generic;
public interface SomeInterface { }
public class SomeImplementation : SomeInterface { }
public static class ExtensionMethods
{
// comment out this line, to make the compiler chose the right method on the line that throws an error below
public static void Method<T>(this T parameter) where T : SomeInterface { }
public static void Method<T>(this IEnumerable<T> parameter) where T : SomeInterface { }
}
class Program
{
static void Main()
{
var instance = new SomeImplementation();
var instances = new List<SomeImplementation>();
// works
instance.Method();
// Error 1 The type 'System.Collections.Generic.List<Test.SomeImplementation>'
// cannot be used as type parameter 'T' in the generic type or method
// 'Test.ExtensionMethods.Method<T>(T)'. There is no implicit reference conversion
// from 'System.Collections.Generic.List<Test.SomeImplementation>' to 'Test.SomeInterface'.
instances.Method();
// works
(instances as IEnumerable<SomeImplementation>).Method();
}
}
}
Method resolution says that closer is better. See the blog post for exact rules.
What does the closer mean? Compiler will see if it can find exact match, if it can't find for some reason it will find next possible compatible methods and so forth.
Let's first make that method compile by removing the SomeInterface constraint.
public static class ExtensionMethods
{
public static void Method<T>(this T parameter) //where T : SomeInterface
{ }
public static void Method<T>(this IEnumerable<T> parameter) //where T : SomeInterface
{ }
}
Now compiler is happy to compile, and do note that both method calls Goes to Method(T) rather than Method(IEnumerable<T>). Why is that?
Because Method(T) is closer in the sense that can take any type as the parameter and also it doesn't require any conversion.
Why is Method(IEnumerable<T>) not closer?
It is because you have the compile time type of the variable as List<T>, so it needs a reference conversion from List<T> to IEnumerable<T>. Which is closer but far from doing no conversions at all.
Back to your question.
Why instances.Method(); doesn't compile?
Again, as said earlier to use Method(IEnumerable<T>) we need some reference conversion, so obviously that's not closer. Now we're left with only one method which is very closer is Method<T>. But the problem is you have constrained it with SomeInterface and clearly List<SomeImplementation>() is not convertible to SomeInterface.
The problem is (am guessing) checking for generic constraints happens after the compiler chooses the closer overload. That invalidates the chosen best overload in this case.
You could easily fix it by changing the static type of the variable to IEnumerable<SomeImplementation> that will work and now you know why.
IEnumerable<SomeImplementation> instances = new List<SomeImplementation>();
Have you tried implementing the first one without generics, as it should behave the same:
public static void Method(this SomeInterface parameter) { /*...*/ }
Or, as Dmitry suggested, by calling the second one the following way:
instances.Method<SomeImplementation>();
But here you need to add the <SomeImplementation> to every call...
While I know you dont want it, I think you should really re-think if method names should be the same. I cannot see how the same name can act on an instance, and collection of such instances. For eg, if your method name is Shoot for T, then the other method should sound like ShootThemAll or something similar.
Or else you should make your assignment slightly different:
IEnumerable<SomeImplementation> instances = new List<SomeImplementation>();
instances.Method(); //now this should work
As a last option, as Dimitry says in comments you have to explicitly specify the type argument.
instances.Method<SomeImplementation>();
Related
I have a generic method that takes a request and provides a response.
public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}
But I don't always want a response for my request, and I don't always want to feed request data to get a response. I also don't want to have to copy and paste methods in their entirety to make minor changes. What I want, is to be able to do this:
public Tre DoSomething<Tres>(Tres response)
{
return DoSomething<Tres, void>(response, null);
}
Is this feasible in some manner? It seems that specifically using void doesn't work, but I'm hoping to find something analogous.
You cannot use void, but you can use object: it is a little inconvenience because your would-be-void functions need to return null, but if it unifies your code, it should be a small price to pay.
This inability to use void as a return type is at least partially responsible for a split between the Func<...> and Action<...> families of generic delegates: had it been possible to return void, all Action<X,Y,Z> would become simply Func<X,Y,Z,void>. Unfortunately, this is not possible.
No, unfortunately not. If void were a "real" type (like unit in F#, for example) life would be a lot simpler in many ways. In particular, we wouldn't need both the Func<T> and Action<T> families - there'd just be Func<void> instead of Action, Func<T, void> instead of Action<T> etc.
It would also make async simpler - there'd be no need for the non-generic Task type at all - we'd just have Task<void>.
Unfortunately, that's not the way the C# or .NET type systems work...
Here is what you can do. As #JohnSkeet said there is no unit type in C#, so make it yourself!
public sealed class ThankYou {
private ThankYou() { }
private readonly static ThankYou bye = new ThankYou();
public static ThankYou Bye { get { return bye; } }
}
Now you can always use Func<..., ThankYou> instead of Action<...>
public ThankYou MethodWithNoResult() {
/* do things */
return ThankYou.Bye;
}
Or use something already made by the Rx team: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx
You could simply use Object as others have suggested. Or Int32 which I have seen some use. Using Int32 introduces a "dummy" number (use 0), but at least you can't put any big and exotic object into an Int32 reference (structs are sealed).
You could also write you own "void" type:
public sealed class MyVoid
{
MyVoid()
{
throw new InvalidOperationException("Don't instantiate MyVoid.");
}
}
MyVoid references are allowed (it's not a static class) but can only be null. The instance constructor is private (and if someone tries to call this private constructor through reflection, an exception will be thrown at them).
Since value tuples were introduced (2017, .NET 4.7), it is maybe natural to use the struct ValueTuple (the 0-tuple, the non-generic variant) instead of such a MyVoid. Its instance has a ToString() that returns "()", so it looks like a zero-tuple. As of the current version of C#, you cannot use the tokens () in code to get an instance. You can use default(ValueTuple) or just default (when the type can be inferred from the context) instead.
I like the idea by Aleksey Bykov above, but it could be simplified a bit
public sealed class Nothing {
public static Nothing AtAll { get { return null; } }
}
As I see no apparent reason why Nothing.AtAll could not just give null
The same idea (or the one by Jeppe Stig Nielsen) is also great for usage with typed classes.
E.g. if the type is only used to describe the arguments to a procedure/function passed as an argument to some method, and it itself does not take any arguments.
(You will still need to either make a dummy wrapper or to allow an optional "Nothing". But IMHO the class usage looks nice with myClass<Nothing> )
void myProcWithNoArguments(Nothing Dummy){
myProcWithNoArguments(){
}
or
void myProcWithNoArguments(Nothing Dummy=null){
...
}
void, though a type, is only valid as a return type of a method.
There is no way around this limitation of void.
What I currently do is create custom sealed types with private constructor. This is better than throwing exceptions in the c-tor because you don't have to get until runtime to figure out the situation is incorrect. It is subtly better than returning a static instance because you don't have to allocate even once. It is subtly better than returning static null because it is less verbose on the call side. The only thing the caller can do is give null.
public sealed class Void {
private Void() { }
}
public sealed class None {
private None() { }
}
UPDATE: As of C# 7.3, this should no longer be an issue. From the release notes:
When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
Pre C# 7.3:
So I read Eric Lippert's 'Constraints are not part of the signature', and now I understand that the spec specifies that type constraints are checked AFTER overload resolution, but I'm still not clear on why this MUST be the case. Below is Eric's example:
static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main()
{
Foo(new Giraffe());
}
This doesn't compile because overload resolution for: Foo(new Giraffe()) infers that Foo<Giraffe> is the best overload match but then the type constraints fail and a compile-time error is thrown. In Eric's words:
The principle here is overload resolution (and method type inference) find the best possible match between a list of arguments and each candidate method’s list of formal parameters. That is, they look at the signature of the candidate method.
Type constraints are NOT part of the signature, but why can't they be? What are some scenarios where it is a bad idea to consider type constraints part of the signature? Is it just difficult or impossible to implement? I'm not advocating that if the best chosen overload is for whatever reason impossible to call then silently fallback to the second best; I would hate that. I'm just trying to understand why type constraints can't be used to influence the choosing of the best overload.
I'm imagining that internally in the C# compiler, for overload resolution purposes only (it doesn't permanently rewrite the method), the following:
static void Foo<T>(T t) where T : Reptile { }
gets transformed to:
static void Foo(Reptile t) { }
Why can't you sort of "pull in" the type constraints into the formal parameter list? How does this change the signature in any bad way? I feel like it only strengthens the signature. Then Foo<Reptile> will never be considered as an overload candidate.
Edit 2: No wonder my question was so confusing. I didn't properly read Eric's blog and I quoted the wrong example. I've edited in the example I think more appropriate. I've also changed the title to be more specific. This question doesn't seem as simple as I first imagined, perhaps I'm missing some important concept. I'm less sure that this is stackoverflow material, it may be best for this question/discussion to be moved elsewhere.
The C# compiler has to not consider type constraints as part as the method signature because they are not part of the method signature for the CLR. It would be disastrous if the overload resolution worked differently for different languages (mainly due to the dynamic binding that may happen at runtime and should not be different from one language to another, or else all hells would break loose).
Why was it decided that these constraints would not be part of the method signature for the CLR is another question alltogether, and I could only make ill informed suppositions about that. I'll let the people in the know answer that.
If T matches multiple constraints, you create an ambiguity that cannot be automatically resolved. For example you have one generic class with the constraint
where T : IFirst
and another with the constraint
where T : ISecond
You now want T to be a class that implements both IFirst and ISecond.
Concrete code example:
public interface IFirst
{
void F();
}
public interface ISecond
{
void S();
}
// Should the compiler pick this "overload"?
public class My<T> where T : IFirst
{
}
// Or this one?
public class My<T> where T : ISecond
{
}
public class Foo : IFirst, ISecond
{
public void Bar()
{
My<Foo> myFoo = new My<Foo>();
}
public void F() { }
public void S() { }
}
I have come across this several times in the last week, and am curious to know the reason - I had a google, but couldn't find anything directly relevant.
I have a class with a dynamic method, and I can add a static method with the same interface:
public class MyClass
{
public int MyMethod()
{
//do something #1;
}
public static int MyMethod()
{
//do something
}
}
This is fine, but if I try to call the static method from the dynamic method, replacing #1 with return MyClass.MyMethod(), I get an error "The call is ambiguous between the following methods or properties: MyClass.MyMethod() and MyClass.MyMethod().
If the static method is deleted, the error changes to "An object reference is required..", which makes sense.
So why is this ambiguous? It has been prefaced with the class name to specify the static method, which works from anywhere else in code.
Why not here?
EDIT: I hadn't actually tried to compile it without the dynamic method calling the static one, I had just gone by VS not underlining it.
But still a similar question I suppose but with an added "Why can't there be both, as one is static, and one not"
Besides here is a similar question on SO, giving some explanation, why you can't have two methods with the same signature.
public class MyClass
{
public int MyMethod()
{
return 0;
}
public static int MyMethod() //Here compiler says, that you've already got method MyMethod with same parameter list
{
return 0;
}
}
So, you can't have those methods at all
Have a look at this
At first:
The signature of a method consists of the name of the method and the
type and kind (value, reference, or output) of each of its formal
parameters, considered in the order left to right. The signature of a
method specifically does not include the return type, nor does it
include the params modifier that may be specified for the right-most
parameter.
Secondly:
Overloading of methods permits a class, struct, or interface to
declare multiple methods with the same name, provided their signatures
are unique within that class, struct, or interface.
EDIT
As for the reason why you get that error: you probably didn't compile yet and see an error underlined with red. If you do compile, you'll see the error underlined with blue not in the line where you call your static method, but on the line where the static method is defined.
So why is this ambiguous? It has been prefaced with the class name to
specify the static method, which works from anywhere else in code. Why
not here?
The reason it is ambiguous is because you could have an instance property on MyClass called MyClass. I believe Eric Lippert describes the reasoning in more detail. I can't quite find that specific post, but here is a similar series from him.
While refactoring some code, I came across this strange compile error:
The constructor call needs to be dynamically dispatched, but cannot be because it is part of a constructor initializer. Consider casting the dynamic arguments.
It seems to occur when trying to call base methods/constructors that take dynamic arguments. For example:
class ClassA
{
public ClassA(dynamic test)
{
Console.WriteLine("ClassA");
}
}
class ClassB : ClassA
{
public ClassB(dynamic test)
: base(test)
{
Console.WriteLine("ClassB");
}
}
It works if I cast the argument to object, like this:
public ClassB(dynamic test)
: base((object)test)
So, I'm a little confused. Why do I have to put this nasty cast in - why can't the compiler figure out what I mean?
The constructor chain has to be determined for certain at compile-time - the compiler has to pick an overload so that it can create valid IL. Whereas normally overload resolution (e.g. for method calls) can be deferred until execution time, that doesn't work for chained constructor calls.
EDIT: In "normal" C# code (before C# 4, basically), all overload resolution is performed at compile-time. However, when a member invocation involves a dynamic value, that is resolved at execution time. For example consider this:
using System;
class Program
{
static void Foo(int x)
{
Console.WriteLine("int!");
}
static void Foo(string x)
{
Console.WriteLine("string!");
}
static void Main(string[] args)
{
dynamic d = 10;
Foo(d);
}
}
The compiler doesn't emit a direct call to Foo here - it can't, because in the call Foo(d) it doesn't know which overload it would resolve to. Instead it emits code which does a sort of "just in time" mini-compilation to resolve the overload with the actual type of the value of d at execution time.
Now that doesn't work for constructor chaining, as valid IL has to contain a call to a specific base class constructor. (I don't know whether the dynamic version can't even be expressed in IL, or whether it can, but the result would be unverifiable.)
You could argue that the C# compiler should be able to tell that there's only actually one visible constructor which can be called, and that constructor will always be available... but once you start down that road, you end up with a language which is very complicated to specify. The C# designers usually take the position of having simpler rules which occasionally aren't as powerful as you'd like them to be.
I saw the following usage of in:
Covariance and contravariance real world example
interface IGobbler<in T> {
void gobble(T t);
}
I don't understand what the usage of in stands for. Does it have relationship with ref, out??
The in and out modifiers in 4.0 are necessary to enforce (or rather: enable) covariance and contravariance.
If you add in, you are only allowed to use T in inwards (contravariant) positions - so things like Add(T obj) is fine, but T this[int index] {get;} is not as this is an outwards (covariant) position.
This is essential for the variance features in 4.0. With variance, ref and out are both unavailable (they are both, and as such: neither).
Ignore what you know about ref and out because it's unrelated to this context. In this case in means that the T will only appear on the right hand side of function names (i.e. in formal parameter lists like void gobble(T t)). If it said out, then T would only appear to the left of function names (i.e. return values like T foo(int x)). The default (not specifying anything) allows T to appear in either place.
In C# 4.0, Contravariance allows for
example, IComparer<X> to be cast to
IComparer<Y> even if Y is a derived
type of X. To achieve this IComparer
should be marked with the In modifier.
public interface IComparer<in T> {
public int Compare(T left, T right);
}
Have look here for example and explanation:
http://www.csharphelp.com/2010/02/c-4-0-covariance-and-contravariance-of-generics/
The in modifier tells you that the type is contravariant and can be implicitly converted to a narrower type. Notice in the example below that even though gobble takes a Shape, it can be assigned to an Action<Rectangle> because we've declared it to be contravariant. This is because anyone calling the delegate and passing it a Rectangle can obviously also pass the Rectangle to a method that takes a Shape as well.
There are some rules for when you use in, and out, but that's what it enables in a nutshell.
For example:
public class Shape { }
public class Rectangle : Shape { }
public interface IGobbler<Shape>
{
void gobble(Shape shape);
}
public class Gobbler : IGobbler<Shape>
{
public void gobble(Shape r) { }
}
public static class Program
{
public static void Main()
{
var g = new Gobbler();
// notice can implictly convert to a narrower type because of the 'in' keyword
Action<Rectangle> r = g.gobble;
}
}
the in and out does not have anything to do with ref and out.
The in keyword is used to describe that in instance of the interface will consume an instance of T. In the example you linked the line
IGobbler<Donkey> dg = new QuadrupedGobbler();
creates a gobbler that you can feed Donkeys to, eventhough the Donkey isn't a QuadrupledCreature, but it derives from it. So you are able to use a more specialized instance instead of the base class as argument.
The out keyword works much the same way, except it's used to describe a thing that produces stuff instead of comsuming it.
In the same example, the line
ISpewer<Rodent> rs = new MouseSpewer();
creates an ISpewer, which when called spews a mouse. A mouse is not a rodent, but derives from it, so you are able to use a producing class that produces more specialized instance than what the interface declares.
Notice how the way the most specialized class is swapped in the two cases. When using the in keyword, you use the specialized class as the generic argument on the interface, whereas in the out case, you use the base class as the generic argument to tell the compiler, that eventhough you create a more specialized class, it should treat it like the base class.
I like to think of it as consumption and production, as these are familiar metaphors for most developers. A method that takes an IGobbler<Cow> can also accept an IGobbler<Animal>, because a Gobbler that can gobble (consume) any Animal can also gobble a Cow. The Gobbler here is a consumer of a specific type of Animal, so it uses the in tag.
The above case (contravariance) can seem counter-intuitive, but think about it from the perspective of the RestaurantOwner who wants a Gobbler<Cow>. If a Gobbler will only gobble Pigs and the RestaurantOwner tries to feed him a Cow, it won't work. He can only accept Gobblers that are less picky, so a Gobbler<Animal> or Gobbler<Herbivore> works fine.
On the other hand, suppose you have a Farmer<Animal> that sells Animals (having a Farm method that returns IEnumerable<Animal>.) If you have a Purchaser that wants to Buy(IEnumerable<Animal>), then it can accept Farmer<Cow>.Farm(), as the Purchaser is willing to buy any produced Animal and Cows are Animals. The Farmer here is a producer of a specific type of Animal, so it uses the `out' tag.
The IN keyword tells the compiler that we only want to use T as an input value.
It will not allow casting from say, IGobbler to IGobbler