c# 判断 泛型t 类型_c# – 为什么无法推断泛型类型的类型参数?

本文探讨了在C#中使用泛型方法时遇到的类型推断问题,特别是在需要约束类型为特定基类如`List`的情况下。作者分享了一个静态类方法的例子,该方法试图输出任何`List`的元素数量,但遇到了编译器的警告和错误。文章解释了编译器无法自动推断所有类型参数的原因,并提供了如何正确约束和调用泛型方法的建议。此外,还通过一个WCF代理包装器的场景展示了这种需求的实际应用。
摘要由CSDN通过智能技术生成

默认情况

让我们假设以下示例性问题 – 我想创建一种方法,它将简单地输出任何List<>中的元素数量.采集.

我用一个方法创建了以下静态类:

public static class MyClass

{

public static void MyMethod(T obj) where T : List // sort of pointless, yes

{

Console.WriteLine(obj.Count);

}

}

请注意,T是List< int>的子类.现在,我可以致电:

List li = new List();

MyClass.MyMethod>(li);

现在,IDE告诉我“类型参数规范是多余的”.它可以从使用情况推断出类型:

List li = new List();

MyClass.MyMethod(li); // OK. li is List, type argument is not required

一般情况

据你记忆,我想输出任何类型的List计数.像这样的东西会很棒:

public static void MyComplexMethod(T obj) where T : List

{

Console.WriteLine(obj.Count);

}

但是,这是一种不正确的语法.我必须实现以下方法:

public static void MyComplexMethod(T1 obj) where T1 : List

{

Console.WriteLine(obj.Count);

}

现在,在不明确描述类型的情况下调用此方法会产生错误“无法从使用中推断出方法的类型参数”:

List li = new List();

MyClass.MyComplexMethod(li); // error

MyClass.MyComplexMethod>(li); // error

MyClass.MyComplexMethod, int>(li); // OK

MyClass.MyComplexMethod, double>(new List()); // OK

MyClass.MyComplexMethod, string>(new List()); // OK

// error. The type must be convertible in order to use...So, compiler knows it

MyClass.MyComplexMethod, double>(new List());

但是,对我来说,似乎这种类型应该可以使用.我提供List< int> – T1是List< int>显然,T2是int.为什么编译器不能这样做?实现理想行为的最合理方法是什么(T:List< any>)?

真实案例

如果有人想知道我为什么需要这个.实际上,当我尝试实现WCF代理包装器时,我偶然发现了这种情况,如下所示:

public static void Call(Action action)

where TServiceProxy : ClientBase, new()

where TServiceContract : class

{

TServiceProxy serviceProxy = new TServiceProxy();

try

{

action(serviceProxy);

serviceProxy.Close();

}

catch (Exception ex)

{

serviceProxy.Abort();

// Log(ex);

throw;

}

}

Service.Call(x => {

int v = DateTime.Now.ToString();

x.Echo(v);

}); // not working

Service.Call(x => {

int v = DateTime.Now.ToString();

x.Echo(v);

}); // not convenient, pointless. EchoServiceClient inherits from ClientBase

没有TServiceProxy:ClientBase< TServiceContract>我将无法执行serviceProxy.Abort().同样,TServiceProxy:ClientBase< any>这将是一个很好的解决方案,因为实际上TServiceContract并不重要 – 它只用于where约束.

最佳答案 您应该考虑您对该类型的实际要求.

在你的情况下,你想做什么?您希望能够在您在方法中创建的客户端上执行操作.该客户端是您作为泛型类型参数传递的类型.您是否需要知道它是ClientBase< something>为了执行动作?没有.

你还对这个对象做了什么?您可以打开和关闭频道.这些是ICommunicationObject确保的行动,ClientBase< T>实现.

这就是你的全部要求.所以你想要有以下约束:

>能够创建该类型的对象.

>实现ICommunicationObject的类型,以便您可以打开/关闭通道.

所以你的方法看起来像这样:

public static void Call(Action action)

where T: ICommunicationObject, new()

{

T serviceProxy = new T();

try

{

action(serviceProxy);

serviceProxy.Close();

}

catch (Exception ex)

{

serviceProxy.Abort();

throw;

}

}

最后,回答您关于编译器无法自动解决此问题的问题:如果您有泛型类型参数,则有两种可能性.编译器能够推断出所有类型参数,在这种情况下您可以将它们排除,或者编译器无法推断所有参数,在这种情况下您需要全部指定它们.毕竟Foo< X>()和Foo< X,Y>()是不同的方法签名,因此如果后者也允许Foo< X>(),则它将是不明确的.

至于为什么编译器无法在您的情况下推断所有类型参数,这仅仅是因为约束给出的类型参数之间的关系不会针对类型推断进行评估.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值