C# 如何区分T和IList<;T>;
我有两种方法:C# 如何区分T和IList<;T>;,c#,generics,C#,Generics,我有两种方法: public static int Insert<T>(this System.Data.IDbConnection connection, T param) public static int Insert<T>(this System.Data.IDbConnection connection, IList<T> param) public static int Insert(this System.Data.IDbConnection,
public static int Insert<T>(this System.Data.IDbConnection connection, T param)
public static int Insert<T>(this System.Data.IDbConnection connection, IList<T> param)
public static int Insert(this System.Data.IDbConnection,T param)
公共静态int-Insert(此System.Data.IDbConnection连接,IList参数)
当我尝试这样的事情时:
connection.Insert(new List<Foo>());
public static int Insert<T>(this IDbConnection connection, T param) where T: Foo
public static int Insert<T>(this IDbConnection connection, List<T> param)
{
return connection.Insert((IList<T>)param);
}
connection.Insert(新列表());
调用了错误的方法(第一个方法)
我怎样才能让它工作 如果存在可以以相同方式隐式调用的泛型重载,则必须使用显式调用 此代码将调用第二个重载
connection.Insert<Foo>(new List<Foo>());
connection.Insert(新列表());
您可以指定泛型类型,而不是依赖类型推断
connection.Insert<Foo>(new List<Foo>());
connection.Insert(新列表());
或者,您可以显式强制转换参数以匹配方法的签名,从而对编译器有所帮助
connection.Insert((IList<Foo>)new List<Foo>());
connection.Insert((IList)new List());
此原型:
public static int Insert<T>(this System.Data.IDbConnection connection, T param)
然后,只有当
T
是Foo
或Foo
的后代时才会调用它。无论是列表
还是IList
都不能从Foo
中降级,这样应该可以解决您的问题。我看到了以下选项:
- 若你们不想重写签名方法,你们应该帮助编译器选择特定的重载
您可以指定泛型参数
:connection.Insert(新列表())代码> 或强制转换到IList
connection.Insert((IList)new List())代码>
- 如果您不想在每次调用该方法时都进行思考,并且可以随意添加更多重载,那么最简单的方法就是为所有可能的
实现添加重载,您将使用如下方式:IList
connection.Insert(new List<Foo>());
public static int Insert<T>(this IDbConnection connection, T param) where T: Foo
public static int Insert<T>(this IDbConnection connection, List<T> param) { return connection.Insert((IList<T>)param); }
public static int Insert(此IDbConnection连接,列表参数) { 返回连接。插入((IList)参数); }
- 如果您根本不想更改公共接口,也不想到处强制转换,则需要更改最通用方法的主体以计算传递的参数,并可能在内部将其传递给其他重载,例如:
public static int Insert<T>(this IDbConnection connection, T param) { if (typeof(T).GetInterfaces() .Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>))) { // method info retrieval should be written more carefully & cached in static var var method = MethodBase.GetCurrentMethod().DeclaringType.GetMethods() .Single(m => m.Name == "Insert" && m.GetParameters() .Select(p => p.ParameterType) .Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IList<>))); var generic = method.MakeGenericMethod(typeof(T).GenericTypeArguments[0]); return (int)generic.Invoke(null, new object[] { connection, param }); } ... }
public static int Insert(此IDbConnection,T参数) { if(typeof(T).GetInterfaces() .Any(x=>x.IsGenericType&&x.GetGenericTypeDefinition()==typeof(IList))) { //方法信息检索应该更仔细地编写&缓存在静态var中 var method=MethodBase.GetCurrentMethod().DeclaringType.GetMethods() .Single(m=>m.Name==“插入”&&m.GetParameters() .Select(p=>p.ParameterType) .Any(t=>t.IsGenericType&&t.GetGenericTypeDefinition()==typeof(IList)); var generic=method.MakeGenericMethod(typeof(T).GenericTypeArguments[0]); return(int)generic.Invoke(null,新对象[]{connection,param}); } ... }
- 好吧,如果你不喜欢这一切-只要像.NET团队的那个家伙一样,把重载重命名为
或类似的东西就行了。在大多数情况下,如果您正在设计公共图书馆,它是最方便的解决方案InsertRange