简体   繁体   中英

Unexpected generic type interface behaviour in C#

I'm reading the famous archived article by Eric Lippert Constraints are not part of the signature . In this article there is an example of code that I'm trying to run in a clean new solution using .NET 2.0:

class Program
{
    class Animal { }
    class Mammal : Animal { }
    class Giraffe : Mammal { }
    class Reptile : Animal { }

    static void Foo<T>(T t) where T : Reptile
    {

    }
    static void Foo(Animal animal)
    {

    }

    static void Main(string[] args)
    {
        Foo(new Giraffe());
        Console.ReadLine();
    }
}

In the article Eric says that:

Most people assume that overload resolution will choose the second overload. In fact, this program produces a compile error saying that T cannot be Giraffe. Is this a compiler bug? No, this behaviour is correct according to the spec.

When I run the code using .NET 2.0 I have no error, the method Foo(Animal animal) is called. The same method called when I pass null instead of Giraffe . I understand that the C# team possibly changed something later, but I use .NET 2.0 here! Using C# 9 I see the same behavior. My question is how I can reproduce the error that Eric mentioned in this article? If I can't reproduce it then I may face the error unexpectedly some day in certain circumstances.

The comments under the question give a general answer, but for those who need more details I think this link that leads to the up-to-date description of Type Interface in C# will be useful: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#type-inference The article is bigger than it is allowed to publish here and I think that over time it will be updated while posting it here may lead later to outdated posted information in this answer. Instead of publishing the entire article I just put here the list of topics this article describes:

  • Type inference process phases;
  • Output type inferences;
  • Explicit parameter type inferences;
  • Exact inferences;
  • Lower-bound inferences;
  • Upper-bound inferences;
  • Fixing;
  • Inferred return type;
  • Type inference for conversion of method groups;
  • Finding the best common type of a set of expressions;
  • Overload resolution;
  • Applicable function member;
  • Better function member;
  • Better conversion from expression;
  • Exactly matching Expression;
  • Better conversion target;
  • Overloading in generic classes;
  • Compile-time checking of dynamic overload resolution;
  • Function member invocation;
  • Invocations on boxed instances.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM