Dan*_*tis 6 c# generics extension-methods overloading
我有一些扩展方法,它们使用Expression参数来引入属性成员并对其进行操作,并且对于成员是IEnumerable <>的特定情况,我有一个重载.但是,从泛型类(对于下面的r4)调用时,它似乎与预期的方法重载不匹配.在课外,选择了正确的方法.
这里发生了什么?这有用还是我需要找到新的方法?
(这是在C#5)
public class Test
{
public void MyTest()
{
// returns "Object"
var r1 = new MyClass<object>().Ext(a => a.Content);
// returns "Enumerable"
var r2 = new MyClass<IEnumerable<object>>().Ext(a => a.Content);
// returns "Object"
var r3 = new MyClass<object>().TestExt();
// returns "Object" (I was expecting "Enumerable")
var r4 = new MyClass<IEnumerable<object>>().TestExt();
// returns "Enumerable"
var r5 = new MyClass<int>().TestExt2();
}
}
public class MyClass<T>
{
public T Content { get; set; }
public IEnumerable<object> OtherContent { get; set; }
public string TestExt()
{
return this.Ext(a => a.Content);
}
public string TestExt2()
{
return this.Ext(a => a.OtherContent);
}
}
public static class MyExtensions
{
public static string Ext<T>(this T obj, Expression<Func<T, IEnumerable<object>>> memberExpression)
{
return "Enumerable";
}
public static string Ext<T>(this T obj, Expression<Func<T, object>> memberExpression)
{
return "Object";
}
}
Run Code Online (Sandbox Code Playgroud)
泛型不是动态类型。要调用的重载在编译时被冻结。当程序稍后运行时,即使变量碰巧持有更具体的运行时类型,也没关系,因为重载在编译时已固定。
你的方法:
public string TestExt()
{
return this.Ext(a => a.Content);
}
Run Code Online (Sandbox Code Playgroud)
必须在编译时绑定到Ext. 由于我们所知道的类中的T( 的类型)是它可以转换为,因此实际上只有一种重载可供选择,因此这对于编译器来说很容易。a.ContentMyClass<T>object
从那时起,TestExt方法体被硬编码为调用Ext.
编辑:这是一个更简单的例子:
static void Main()
{
IEnumerable<object> e = new List<object>();
var r = Generic(e);
}
static string Generic<T>(T x)
{
return Overloaded(x);
}
static string Overloaded(IEnumerable<object> x)
{
return "Enumerable";
}
static string Overloaded(object x)
{
return "Object";
}
Run Code Online (Sandbox Code Playgroud)
正如你现在所理解的,r变成"Object"。
(T例如,如果您以某种方式进行限制where T : IEnumerable<object>,事情就会有所不同)。
对于运营商来说也是如此。例如,该==运算符是重载的,因为它以一种方式用于一般引用类型,而以另一种方式用于字符串。因此,在下面的示例中,运算符扮演了之前的==角色:Overloaded
static void Main()
{
string str1 = "abc";
string str2 = "a";
str2 += "bc"; // makes sure this is a new instance of "abc"
bool b1 = str1 == str2; // true
bool b2 = Generic(str1, str2); // false
}
static bool Generic<T>(T x, T y) where T : class
{
return x == y;
}
Run Code Online (Sandbox Code Playgroud)
哪里b2变成false.