This question already has answers here:
Can’t assign to delegate an anonymous method with less specific parameter type
(3 answers)
Closed 5 years ago.
The second test method below does not compile (cannot convert lambda expression to target type D1). Does that mean that (non-generic) delegate contravariance does not work with lambda expressions?
[TestFixture]
public class MyVarianceTests
{
private abstract class Animal {}
private class Tiger : Animal {}
private delegate Type D1(Tiger tiger);
private static Type M1(Animal animal)
{
return animal.GetType();
}
[Test]
public void ContravariantDelegateWithMethod()
{
D1 func = M1;
Type result = func(new Tiger());
Assert.AreEqual(result, typeof (Tiger));
}
[Test]
public void ContravariantDelegateWithLambda()
{
D1 func = (Animal animal) => animal.GetType();
Type result = func(new Tiger());
Assert.AreEqual(result, typeof (Tiger));
}
}
You've identified an inconsistency in the language.
This is called out explicitly in the language specification:
7.15.1 Anonymous function signatures
[...] In contrast to method group conversions (§6.6), contra-variance of anonymous function
parameter types is not supported. [...]
...which raises the question:
Why didn't the language designers bother supporting this feature?
<speculation>
Clearly, the feature has some small benefits. But does it justify the costs of the extra complications required in a compliant compiler implementation?
When you write a lambda expression, you must already know exactly which delegate/expression-tree type it is being converted to (there's no general-purpose type that can "hold" an arbitrary lambda). As of C# 5, a lambda (in contrast to a method) serves absolutely no purpose other than to help in the creation of a single delegate / expression-tree instance. Consequently, there's no advantage (other than convenience) to explicitly specifying a more general type than required for a parameter and expecting contra-variance support from the compiler. You could just omit the type completely and rely on type-inference (or, worst case, explicitly specify the exact parameter-type required) without any loss in reusability or expressibility.
This obviously doesn't apply to methods, which serve other purposes other than the creation of delegates/expression-trees. You may desire a particular function signature (different from the delegate's) because it is the most appropriate, or require it because it must satisfy an interface contract. Further more, consider that you (as the programmer creating the delegate/expression-tree) don't necessarily "own" the method in question (it could be in a third-party assembly) when you are performing a method-group conversion. This is never the case with lambdas.
It appears the language-designers felt the benefits of implementing contra-variance of parameter types for lambdas didn't justify the costs, unlike for method-groups.
</speculation>
D1 excepts an argument of type Tiger but you're passing in a type of Animal.
Animal is not a Tiger
But Tiger is an Animal
Related
I need more information about variance in generics and delegates. The following code snippet does not compile:
Error CS1961 Invalid variance: The type parameter 'TIn' must be
covariantly valid on 'Test.F(Func)'. 'TIn' is
contravariant.
public interface Test<in TIn, out TOut>
{
TOut F (Func<TIn, TOut> transform);
}
The .net Func definition is as follows:
public delegate TResult Func<in T, out TResult> (T arg);
Why the compiler complains about TIn being contravariant and TOut - covariant while the Func expects exactly the same variance?
EDIT
The main constraint for me is that I want my Test interface to have TOut as covariant in order to use it something like this:
public Test<SomeClass, ISomeInterface> GetSomething ()
{
return new TestClass<SomeClass, AnotherClass> ();
}
Given that public class AnotherClass : ISomeInterface.
I need more information about variance in generics and delegates.
I wrote an extensive series of blog articles on this feature. Though some of it is out of date -- since it was written before the design was finalized -- there's lots of good information there. In particular if you need a formal definition of what variance validity is, you should carefully read this:
https://blogs.msdn.microsoft.com/ericlippert/2009/12/03/exact-rules-for-variance-validity/
See my other articles on my MSDN and WordPress blogs for related topics.
Why the compiler complains about TIn being contravariant and TOut - covariant while the Func expects exactly the same variance?
Let's slightly rewrite your code and see:
public delegate R F<in T, out R> (T arg);
public interface I<in A, out B>{
B M(F<A, B> f);
}
The compiler must prove that this is safe, but it is not.
We can illustrate that it is not safe by supposing that it is, and then discovering how it can be abused.
Let's suppose we have an Animal hierarchy with the obvious relationships, eg, Mammal is an Animal, Giraffe is a Mammal, and so on. And let's suppose that your variance annotations are legal. We should be able to say:
class C : I<Mammal, Mammal>
{
public Mammal M(F<Mammal, Mammal> f) {
return f(new Giraffe());
}
}
I hope you agree this is a perfectly valid implementation. Now we can do this:
I<Tiger, Animal> i = new C();
C implements I<Mammal, Mammal>, and we've said that the first one can get more specific, and the second can get more general, so we've done that.
Now we can do this:
Func<Tiger, Animal> f = (Tiger t) => new Lizard();
That's a perfectly legal lambda for this delegate, and it matches the signature of:
i.M(f);
And what happens? C.M is expecting a function that takes a giraffe and returns a mammal, but it's been given a function that takes a tiger and returns a lizard, so someone is going to have a very bad day.
Plainly this must not be allowed to happen, but every step along the way was legal. We must conclude that the variance itself was not provably safe, and indeed, it was not. The compiler is right to reject this.
Getting variance right takes more than simply matching the in and out annotations. You've got to do so in a manner that does not allow this sort of defect to exist.
That explains why this is illegal. To explain how it is illegal, the compiler must check that the following is true of B M(F<A, B> f);:
B is valid covariantly. Since it is declared "out", it is.
F<A, B> is valid contravariantly. It is not. The relevant portion of the definition of "valid contravariantly" for a generic delegate is: If the ith type parameter was declared as contravariant, then Ti must be valid covariantly. OK. The first type parameter, T, was declared as contravariant. Therefore the first type argument A must be valid covariantly. But it is not valid covariantly, because it was declared contravariant. And that's the error you're getting. Similarly, B is also bad because it must be valid contravariantly, but B is covariant. The compiler does not go on to find additional errors after it finds the first problem here; I considered it but rejected it as being a too-complex error message.
I note also that you would still have this problem even if the delegate were not variant; nowhere in my counterexample did we use the fact that F is variant in its type parameters. A similar error would be reported if we tried
public delegate R F<T, R> (T arg);
instead.
Variance is about being able to replace type parameters with either more or less derived types than originally declared. For example, IEnumerable<T> is covariant for T, meaning if you start with a reference to a IEnumerable<U> object, you can assign that reference to a variable having type IEnumerable<V>, where V is assignable from U (e.g. U inherits V). This works, because any code trying to use the IEnumerable<V> wants to receive only values of V, and since V is assignable from U, receiving only values of U is also valid.
For covariant parameters like T, you have to assign to a type where the destination type is the same as T, or assignable from T. For contravariant parameters, it has to go the other way. The destination type has to be the same as, or assignable to, the type parameter.
So, how does the code you are trying to write work in that respect?
When you declare Test<in TIn, out TOut>, you are promising that it will be valid to assign an instance of that interface Test<TIn, TOut> to any destination having the type Test<U, V> where U can be assigned to TIn and TOut can be assigned to V (or they are identical, of course).
At the same time, let's consider what your transform delegate is to expect. The Func<T, TResult> type variance requires that if you want to assign that value to something else, it also meets the variance rules. That is, a destination Func<U, V> must have U assignable from T, and TResult assignable from V. This ensures that your delegate target method which is expecting to receive a value of U will get one of those, and the value returned by the method, having type V, can be accepted by the code receiving it.
Importantly, your interface method F() is the one doing the receiving! The interface declaration promises that TOut will be used only as output from the interface members. But through the use of the transform delegate, the method F() will receive a value of TOut, making that input to the method. Likewise, the method F() is allowed to pass a value of TIn to the transform delegate, making that an output of your interface implementation, even though you've promised that TIn is used only as input.
In other words, every layer of call reverses the sense of the variance. Members in the interface have to use covariant type parameters as output only and contravariant parameters as input only. But those parameters become reversed in sense when they are used in delegate types passed to or returned from interface members, and have to comply with the variance in that respect.
A concrete example:
Suppose we have an implementation of your interface, Test<object, string>. If the compiler were to allow your declaration, you'd be permitted to assign a value of that implementation Test<object, string> to a variable having the type Test<string, object>. That is, the original implementation promises to allow as input any thing having type object and return only values having the type string. It's safe for code declared as Test<string, object> to work with this, because it will pass string objects to an implementation that requires objects values (string is an object), and it will receive values having the type object from an implementation that returns string values (again, string is an object, so also safe).
But your interface implementation expects code to pass a delegate of type Func<object, string>. If you were allowed to treat (as above) your interface implementation as a Test<string, object> instead, then the code using your re-cast implementation would be able to pass a delegate of Func<string, object> to the method F(). The method F() in the implementation is allowed to pass any value of type object to the delegate, but that delegate, being of type Func<string, object>, is expecting only values having the type string to be passed to it. If F() passes something else, e.g. just a plain old new object(), the delegate instance won't be able to use it. It's expecting a string!
So, in fact, the compiler is doing exactly what it's supposed to: it's preventing you from writing code that is not type-safe. As declared, if you were permitted to use that interface in a variant way, you would in fact be able to write code that while allowed at compile-time, could break at run-time. Which is the exact opposite of the whole point of generics: to be able to determine at compile-time that the code is type-safe!
Now, how to solve the dilemma. Unfortunately, there's not enough context in your question to know what the right approach is. It's possible that you simply need to give up on variance. Often, there's not actually any need to make types variant; it's a convenience in some cases, but not required. If that's the case, then just don't make the interface's parameters variant.
Alternatively, it's possible you really do want the variance and thought it would be safe to use the interface in a variant way. That's harder to solve, because your fundamental assumption was just incorrect and you will need to implement the code some other way. The code would compile if you could reverse the parameters in the Func<T, TResult>. I.e. make the method F(Func<TOut, TIn> transform). But there's not anything in your question that suggests that's actually possible in your scenario.
Again, without more context it's impossible to say what "other way" would work for you. But, hopefully now that you understand the hazard in the code the way you've written it now, you can revisit the design decision that led you to this not-type-safe interface declaration, and can come up with something that works. If you have trouble with that, post a new question that provides more detail as to why you thought this would be safe, how you're going to use the interface, what alternatives you've considered, and why none of those work for you.
TIn = the class knows how to read it, and the implementation is allowed to treat it as a type that is less derived than it actually is. You might pass it an instance that is more derived than expected, but that doesn't matter, because the derived class can do everything that the base class can do.
TOut = the implementation knows to to produce one, and the implementation is allowed to produce a type that is more derived than the caller is expecting. Again, it doesn't matter-- the caller can assign a more derived class to a less derived variable with no problem.
But--
If you pass the class a Func<TIn, TOut>, and you expect the class to be able to call it, then the class will have to be able to produce a TIn and read the TOut. Which is the opposite of the above.
Why can't it? Well, I already mentioned that the class can treat TIn as something that is less derived. If it attempts to call the function with an argument that is less derived, it won't work (what if the function is expecting to be able to call string.Length but the class passes it an object?). Also, if it attempts to read the results of the function as something that is more derived, that will fail as well.
You can eliminate the problem by eliminating the variance-- get rid of the in and out keywords-- which will render the class unable to substitute less/more derived types (this is called "invariance") but will allow you to both read and write the types.
Remove in and out -keywords from the interface definition:
public interface Test<TIn, TOut>{
TOut F (Func<TIn, TOut> transform);
}
remove the in and out key words:
public interface Test<TIn, TOut>
{
TOut F (Func<TIn, TOut> transform);
}
you can read about the meaning of them here:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-generic-modifier
A type can be declared contravariant in a generic interface or delegate if it is used only as a type of method arguments and not used as a method return type
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-generic-modifier
The type parameter is used only as a return type of interface methods and not used as a type of method arguments.
I would like to define a non-generic delegate extending a generic delegate to define a default for the generic delegate type parameter, i.e. something like this (not a valid piece of C# code but an obvious-to-understand illustration for the concept I mean hopefully):
public delegate void MyDelegate<T>(T arg);
public delegate void MyDelegate(object arg) : MyDelegate<object>;
What is, if any, the correct way to declare this?
Needless to say I can just declare 2 independent delegates to achieve virtually same effect a way like this:
public delegate void MyDelegate<T>(T arg);
public delegate void MyDelegate(object arg);
but I'd like to do to make the actual relation between them (the fact a bare MyDelegate type is meant to equal MyDelegate<object>, the way like a class extending another class or literally) definite and make the following code will become valid if possible:
MyDelegate<object> d1;
MyDelegate d2;
MyDelegate d1 = d2;
Sorry, I may have been too harsh in saying you should know delegate types are sealed. It is clear in the specification, but I took a look at the latest version of the MSDN language documentation, and it does not seem to mention this at all. Well, anyway…they are sealed. 😊 You can't create a new class that inherits a delegate type, and you certainly can't use the delegate keyword to declare a new delegate type that inherits another delegate type (the keyword has a very specific syntax, and doesn't even allow an inheritance syntax).
It's still not really clear to me what you're trying to do. But, in some sense, a delegate type is an interface with just one member. It's more flexible, of course, because the implementation isn't in a single type, but can be any method from any type. But conceptually, the two are very similar.
In that sense, you could express your intent in code using an interface instead of a delegate. For example:
interface IDelegate<T>
{
void M(T arg);
}
interface IDelegateObject : IDelegate<object> { }
Of course, the problem with this is that now you need some type that will implement the interface in question. Any given type will only be able to implement any given interface once, so you lose a lot of the flexibility that delegate types would ordinarily give you.
But, you can do something like this:
IDelegate<object> d1;
IDelegateObject d2;
d1 = d2;
That is, since IDelegateObject inherits IDelegate<object>, and thus "is a" IDelegate<object>, you can then assign a value of type IDelegateObject, i.e. d2, to a variable of type IDelegate<object>, i.e. d1.
I'm a beginner with C# and can't find any answer for this :
Im trying to delegate Actions with some interface parameter , but push through functions with objects that extend this interface (or class)
// some class extending interface
public class IntEvent : IFace{}
public class MoveEvent : IFace{}
// function i like to use to verify Action
static void setAction(Action<IFace> evt) {
// evt ...
}
// function to delegate as Action
static void evtCheck(IntEvent evt) {
// some func
}
static void evtMove(MoveEvent evt) {
// some func
}
// class {
// call method inside class and delegate this function :
setAction(evtCheck);
setAction(evtMove);
I'm receiving an error that "evtCheck(IntEvent) cannot be converted to Action<IFace>" , even if IntEvent extends the IFace interface .
How should I solve this ? Maybe I have to use Func or Delegate ?
You can't do what you're trying to do - you're expecting covariance, but Action<T> is contravariant on its only type-parameter.
You can't do a method-group conversion from evtCheck to Action<IFace> because evtCheck needs a more specific type (IntEvent) as its argument than the more general IFace type that an Action<IFace> instance expects. If such a conversion were allowed, what would you expect to happen if the delegate were executed with an argument that implements IFace but is not an IntEvent?
I think you should have another look at your design because it looks like there's a flaw there, but if you want, you can create a lambda to force a cast of the argument to the desired type and accept the possibility of an InvalidCastException:
setAction(iFace => evtCheck((IntEvent)iface));
More likely, you might want to make evtCheck accept a more general type or setAction to accept a more specific delegate.
Action<T> is contravariant in T, so methods taking an Action<T> will also accept Action<U> where T is derived from U.
Your IntEvent class, however, implements the IFace interface, which means that if the compiler accepted your setAction() call, it would be possible to call evtCheck() with an argument that is another IFace-derivative and not IntEvent, a runtime error and a clear violation of type safety.
Obligatory Eric Lippert reference: Covariance and contravariance
EDIT: from your description it seems to me that what you really want is differentiation based on the method parameter's type, so e.g. you want a separate action for IntEvent, another one for (a hypothetical) DoubleEvent etc. If this is the case, you are actually after double virtual dispatch, which is not directly supported in C#, but you can simulate it using the Visitor design pattern.
Suppose I have two classes:
class a
{
public void sayGoodbye() { Console.WriteLine("Tschüss"); }
public virtual void sayHi() { Console.WriteLine("Servus"); }
}
class b : a
{
new public void sayGoodbye() { Console.WriteLine("Bye"); }
override public void sayHi() { Console.WriteLine("Hi"); }
}
If I call a generic method that requires type 'T' to be derived from class 'a':
void call<T>() where T : a
Then inside that method I call methods on an instance of type 'T' the method call are bound to type 'a', as if the instance was being cast as 'a':
call<b>();
...
void call<T>() where T : a
{
T o = Activator.CreateInstance<T>();
o.sayHi(); // writes "Hi" (virtual method)
o.sayGoodbye(); // writes "Tschüss"
}
By using reflection I am able to get the expected results:
call<b>();
...
void call<T>() where T : a
{
T o = Activator.CreateInstance<T>();
// Reflections works fine:
typeof(T).GetMethod("sayHi").Invoke(o, null); // writes "Hi"
typeof(T).GetMethod("sayGoodbye").Invoke(o, null); // writes "Bye"
}
Also, by using an interface for class 'a' I get the expected results:
interface Ia
{
void sayGoodbye();
void sayHi();
}
...
class a : Ia // 'a' implements 'Ia'
...
call<b>();
...
void call<T>() where T : Ia
{
T o = Activator.CreateInstance<T>();
o.sayHi(); // writes "Hi"
o.sayGoodbye(); // writes "Bye"
}
The equivalent non-generic code also works fine:
call();
...
void call()
{
b o = Activator.CreateInstance<b>();
o.sayHi(); // writes "Hi"
o.sayGoodbye(); // writes "Bye"
}
Same thing if I change the generic constraint to 'b':
call<b>();
...
void call<T>() where T : b
{
T o = Activator.CreateInstance<T>();
o.sayHi(); // writes "Hi"
o.sayGoodbye(); // writes "Bye"
}
It seems that the compiler is generating method calls to the base class specified in the constraint, so I guess I understand what is happening, but this is not what I expected. Is this really the correct result?
Generics aren't C++ Templates
Generics are a general type: there will be only one generic class (or method) output by the compiler. Generics doesn't work by compile-time replacing T with the actual type provided, which would require compiling a separate generic instance per type parameter but instead works by making one type with empty "blanks". Within the generic type the compiler then proceeds to resolve actions on those "blanks" without knowledge of the specific parameter types. It thus uses the only information it already has; namely the constraints you provide in addition to global facts such as everything-is-an-object.
So when you say...
void call<T>() where T : a {
T o = Activator.CreateInstance<T>();
o.sayGoodbye();//nonvirtual
...then type T of o is only relevant at compile time - the runtime type may be more specific. And at compile time, T is essentially a synonym for a - after all, that's all the compiler knows about T! So consider the following completely equivalent code:
void call<T>() where T : a {
a o = Activator.CreateInstance<T>();
o.sayGoodbye();//nonvirtual
Now, calling a non-virtual method ignores the run-time type of a variable. As expected, you see that a.sayGoodbye() is called.
By comparison, C++ templates do work the way you expect - they actually expand the template at compile time, rather than making a single definition with "blanks", and thus the specific template instances can use methods only available to that specialization. As a matter of fact, even at run-time, the CLR avoids actually instantiating specific instances of templates: since all the calls are either virtual (making explicit instantiation unnecessary) or non-virtual to a specific class (again, no point in instantiating), the CLR can use the same bytes - probably even the same x86 code - to cover multiple types. This isn't always possible (e.g. for value types), but for reference types that saves memory and JIT-time.
Two more things...
Firstly, your call method uses Activator - that's not necessary; there's an exceptional constraint new() you may use instead that does the same thing but with compile-time checking:
void call<T>() where T : a, new() {
T o = new T();
o.sayGoodbye();
Attempting to compile call<TypeWithoutDefaultConstructor>() will fail at compile time with human-readable message.
Secondly, it may seem as though generics are largely pointless if they're just blanks - after all, why not simply work on a-typed variables all along? Well, although at compile-time you can't rely on any details a sub-class of a might have within the generic method, you're still enforcing that all T are of the same subclass, which allows in particular the usage of the well-known containers such as List<int> - where even though List<> can never rely on int internals, to users of List<> it's still handy to avoid casting (and related performance and correctness issues).
Generics also allow richer constraints than normal parameters: for example, you can't normally write a method that requires its parameter to be both a subtype of a and IDisposable - but you can have several constraints on a type parameter, and declare a parameter to be of that generic type.
Finally, generics may have run-time differences. Your call to Activator.CreateInstance<T>() is a perfect illustration of that, as would be the simple expression typeof(T) or if(myvar is T).... So, even though in some sense the compiler "thinks" of the return type of Activator.CreateInstance<T>() as a at compile time, at runtime the object will be of type T.
sayGoodbye is not virtual.
The compiler only "knows" T is of type a. It will call sayGoodbye on a.
On type b you redefine sayGoodbye, but the compiler is not aware of type b. It cannot know all derivates of a. You can tell the compiler that sayGoodbye may be overriden, by making it virtual. This will cause the compiler to call sayGoodbye on a special way.
Method hiding is not the same as polymorphism, as you've seen. You can always call the A version of the method simply by downcasting from B to A.
With a generic method, with T constrained to type A, there is no way for the compiler to know whether it could be some other type, so it would be very unexpected, in fact, for it to use a hiding method rather than the method defined on A. Method hiding is for convenience or interoperability; it has nothing to do with substituting behavior; for that, you need polymorphism and virtual methods.
EDIT:
I think the fundamental confusion here is actually Generics vs. C++ style templates. In .NET, there is only one base of code for the generic type. Creating a specialized generic type does not involve emitting new code for the specific type. This is different from C++, where a template specialization involves actually creating and compiling additional code, so that it will be truly specialized for the type specified.
The new keyword is kind of a hack in C#. It contradicts polymorphism, because the method called depends on the type of the reference you hold.
Method overloading allows us to define many methods with the same name but with a different set of parameters ( thus with the same name but different signature ).
Are these two methods overloaded?
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
EDIT:
Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same name and same signature?
Are the two methods overloaded?
Yes.
Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same signature?
The question doesn't make sense; A is not a generic type as you have declared it. Perhaps you meant to ask:
Should the statement A.MyMethod(myInt); cause the compiler to report an error, since there are two ambiguous candidate methods?
No. As others have said, overload resolution prefers the non-generic version in this case. See below for more details.
Or perhaps you meant to ask:
Should the declaration of type A be illegal in the first place, since in some sense it has two methods with the same signature, MyMethod and MyMethod<int>?
No. The type A is perfectly legal. The generic arity is part of the signature. So there are not two methods with the same signature because the first has generic arity zero, the second has generic arity one.
Or perhaps you meant to ask:
class G<T>
{
public static void M(T t) {}
public static void M(int t) {}
}
Generic type G<T> can be constructed such that it has two methods with the same signature. Is it legal to declare such a type?
Yes, it is legal to declare such a type. It is usually a bad idea, but it is legal.
You might then retort:
But my copy of the C# 2.0 specification as published by Addison-Wesley states on page 479 "Two function members declared with the same names ... must have have parameter types such that no closed constructed type could have two members with the same name and signature." What's up with that?
When C# 2.0 was originally designed that was the plan. However, then the designers realized that this desirable pattern would be made illegal:
class C<T>
{
public C(T t) { ... } // Create a C<T> from a given T
public C(Stream s) { ... } // Deserialize a C<T> from disk
}
And now we say sorry buddy, because you could say C<Stream>, causing two constructors to unify, the whole class is illegal. That would be unfortunate. Obviously it is unlikely that anyone will ever construct this thing with Stream as the type parameter!
Unfortunately, the spec went to press before the text was updated to the final version. The rule on page 479 is not what we implemented.
Continuing to pose some more questions on your behalf:
So what happens if you call G<int>.M(123) or, in the original example, if you call A.MyMethod(123)?
When overload resolution is faced with two methods that have identical signatures due to generic construction then the one that is generic construction is considered to be "less specific" than the one that is "natural". A less specific method loses to a more specific method.
So why is it a bad idea, if overload resolution works?
The situation with A.MyMethod isn't too bad; it is usually pretty easy to unambiguously work out which method is intended. But the situation with G<int>.M(123) is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type G<int>. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
https://ericlippert.com/2006/04/05/odious-ambiguous-overloads-part-one/
https://ericlippert.com/2006/04/06/odious-ambiguous-overloads-part-two/
Yes. MyMethod(int myVal) will be called when the type of the parameter is an int, the generic overload will be called for all other parameter arguments, even when the parameter argument is implicitly convertible to (or is a derived class of) the hardcoded type. Overload resolution will go for the best fit, and the generic overload will resolve to an exact match at compile time.
Note: You can explicitly invoke the generic overload and use an int by providing the type parameter in the method call, as Steven Sudit points out in his answer.
short s = 1;
int i = s;
MyMethod(s); // Generic
MyMethod(i); // int
MyMethod((int)s); // int
MyMethod(1); // int
MyMethod<int>(1); // Generic**
MyMethod(1.0); // Generic
// etc.
Yes, they are. They will allow code as such:
A.MyMethod("a string"); // calls the generic version
A.MyMethod(42); // calls the int version
Yes, they are overloaded. The compiler is supposed to prefer explicit method signatures against generic methods if they are available. Beware, however, that if you can avoid this kind of overload you probably should. There have been bug reports with respect to this sort of overload and unexpected behaviors.
https://connect.microsoft.com/VisualStudio/feedback/details/522202/c-3-0-generic-overload-call-resolution-from-within-generic-function
Yes. They have the same name "MyMethod" but different signatures. The C# specification, however, specifically handles this by saying that the compiler will prefer the non-generic version over the generic version, when both are options.
Yes. Off the top of my head, if you call A.MyMethod(1);, it will always run the second method. You'd have to call A.MyMethod<int>(1); to force it to run the first.