2012-01-28 151 views
5

我是堆栈溢出的一个newby,所以请在我身上轻松一下!我正在深入阅读C#,但我遇到了一个我不相信的场景。对网络的快速搜索也没有发现任何结果。泛型方法的类型参数的类型推断

说我定义以下重载方法:

void AreEqual<T>(T expected, T actual) 

void AreEqual(object expected, object actual) 

如果我打电话AreEqual()没有指定类型参数:

AreEqual("Hello", "Hello") 

调用该方法的通用或非通用版本?泛型方法是在推断出类型参数的情况下调用的,还是调用方法参数隐式转换为System.Object的非泛型方法?

我希望我的问题很清楚。提前感谢您的任何建议。

+5

你当然可以写一些简单的代码来检查这个... – 2012-01-28 01:43:21

+1

http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx – 2012-01-28 01:56:51

+0

@米奇麦 - 真实的,但我不会做我的第一篇文章。它对其他人在这里看到答案很有用。 – zekesteer 2012-01-28 02:01:51

回答

5

该仿制药可以生成功能AreEqual(string, string)。这比AreEqual(object, object)更接近匹配,因此选择通用函数。

有趣的是,即使编译器会导致约束违规错误,编译器也会选择这个通用函数。

请看下面的例子:

using System.Diagnostics; 

namespace ConsoleSandbox 
{ 
    interface IBar 
    { 
    } 

    class Program 
    { 
     static void Foo<T>(T obj1) where T: IBar 
     { 
      Trace.WriteLine("Inside Foo<T>"); 
     } 


     static void Foo(object obj) 
     { 
      Trace.WriteLine("Inside Foo Object"); 
     } 

     static void Main(string[] args) 
     { 

      Foo("Hello"); 
     } 
    } 
} 

即使在这里,会选择在非通用版本的通用版本。然后你得到这个错误:

The type 'string' cannot be used as type parameter 'T' in the generic type or method 'ConsoleSandbox.Program.Foo(T)'. There is no implicit reference conversion from 'string' to 'ConsoleSandbox.IBar'.

但如果添加了一个功能Foo(string obj1)它会工作。

+0

很好的答案,谢谢!很好的例子,我自己试了一下,以确认:-) – zekesteer 2012-01-28 01:58:12

+0

请注意,重载解析是由C#编译器完成的,而不是.NET框架。 – phoog 2012-01-28 03:58:53

+0

@phoog - 谢谢,我已经改变了措辞 – 2012-01-28 04:31:55