加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

接收List的C#泛型方法不会为实际类型的T调用重载方法(更喜欢通用

发布时间:2020-12-15 23:50:43 所属栏目:百科 来源:网络整理
导读:参见英文答案 why is this generic not resolved at compile time?????????????????????????????????????4个 我有这个例子C#代码: class Stuff { } // empty classvoid Main(){ var list = new ListStuff { new Stuff(),new Stuff() }; Fun(list);}void Fun
参见英文答案 > why is this generic not resolved at compile time?????????????????????????????????????4个
我有这个例子C#代码:

class Stuff { }  // empty class

void Main()
{
    var list = new List<Stuff> {
        new Stuff(),new Stuff()
    };
    Fun(list);
}

void Fun<T>(List<T> a)
{
    Debug.Log("called List<T> Fun");
    foreach (T t in a) {
        Fun(t);
    }
}

void Fun(Stuff a)
{
    Debug.Log("called Stuff Fun");
}

void Fun<T>(T a)
{
    Debug.Log("called T Fun");
}

调用Main()最终打印:

called List<T> Fun
called T Fun
called T Fun

我不明白为什么编译器能够按预期调用Fun< T>(List< T> a),但后来不知道调用Fun(Stuff a),这比Fun< T>(T更具体)一个).在这种情况下,在编译时是否确定T是Stuff?在Fun< T>(List< T> a)中打印typeof(T)给出了“Stuff”如预期的那样,但这不是任何事情的证据……

添加Fun(List< Stuff> a)方法有效但不可取(项目中列表有许多不同的可能类型,并且所有这些行为都应该相同).

我试过搜索这个问题,但无法用我能找到它的方式来表达它.对不起,如果之前有人问过这个问题(可能!).

解决方法

关键是要理解void Fun< T>(List< T> a)被编译一次,重载决议执行一次.不是每T一次,而是一次.

在编译此代码时考虑编译器的情况:

void Fun<T>(List<T> a)
{
    Debug.Log("called List<T> fun");
    foreach (T t in a) {
        Fun(t);
    }
}

特别是,考虑Fun(t)调用中的重载决策.

编译器对T一无所知,这是Fun(t)调用中参数的类型 – 它可以是任何非指针类型.它必须在这些签名之间执行重载解析:

void Fun<T>(List<T> a)
void Fun(Stuff a)
void Fun<T>(T a)

这些方法中唯一适用的是最后一个 – 调用代码中的T用作我们调用的方法中T的类型参数,并且没问题.其他两种方法不适用,因为没有从T到List< TList>的转换. (对于任何TList),或从T到Stuff.

如果您希望在执行时执行重载决策,则可以使用动态类型:

foreach (dynamic d in a) {
    Fun(d);
}

我个人并不喜欢这样做,但在这种情况下它可能会做你想要的.另一方面,对于嵌套列表,它可能会变得棘手 – 如果你是一个List< int>,那么你期望它调用Fun< List< int>>(list)或Fun< int>(list)?老实说,我不记得规则,知道哪些是“更好”或是否含糊不清.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读