gpt4 book ai didi

visual-studio-2010 - C# 编译器允许接口(interface)代替通用派生版本?

转载 作者:行者123 更新时间:2023-12-04 06:14:15 25 4
gpt4 key购买 nike

我对编译器无法理解的某些行为感到有些困惑。我已将其简化为以下代码示例:

    public interface IFoo { }
public interface IBar<T> : IFoo { }
public delegate void DHandler<T>(IBar<T> arg);

public static class Demo
{
static void Garply<T>(DHandler<T> handler) { }

public static void DoStuffWithInt()
{
Garply<int>(Handler);
}

static void Handler(IFoo arg) { }
}

我的问题是我不希望代码编译,但它编译了。我不希望它编译因为 DHandler<int>需要 IBar<int>在签名中,但是 Handler方法声明 IFoo不是 IBar<int> (尽管反之亦然)。因此 Handler不是 DHandler<int>因此它的委托(delegate)不能用作 Garply<int> 的参数打电话。

如果我将代码更改为 Handler(IBar<int> arg)它编译。如果我将其更改为 Handler(IBar<string> arg)它没有。这两种行为都符合我的预期。

提示这个问题的实际问题是,当签名为Handler(IBar<int> arg)时,编译器提示我需要显式指定 Garply 的类型参数称呼。在这个例子中微不足道,但在实际代码中,这将是一个真正的麻烦。我很困惑,因为关于 Garply 的争论是一个带有签名的方法 (IBar<int> arg) ,因此它的代表将是 DHandler<int> ,所以选择了Garply<T>毫无疑问是Garply<int> .但显然编译器看到了歧义。它正在调查,这让我想到了上面的难题,我只能猜测编译器可能在想“好吧,令杰森惊讶的是,我已经接受了一个 IFoo 对于这个 IBar<T> ,所以一个 T必须指定让我知道我应该将它编译为 IBar<T> 而不是 IFoo ”。这或许可以解释为什么它需要类型参数。但是任何人都可以阐明这一点吗?

最佳答案

这是在 C# 2 中引入的委托(delegate)方差。这与 C# 4 中引入的通用方差不同

这是一个更简单的例子:

delegate void Foo(string x);    

class Test
{
static void Main()
{
Foo foo = Bar;
}

static void Bar(object y) {}
}

重点是我们可以创建 Foo 的实例来自 Bar 的代表方法因为Bar只要给定 any 就会工作 object .当 Foo delegate 被调用,它总是提供一个 string引用,并且有来自 string 的引用转换至 object .所以如果我有:

Foo f = ...;
f("fred");

...那个电话总是适合Bar .

同样在你的情况下,任何调用Garply<T>handler 制作肯定是对Handler的有效调用- 所以编译器很乐意创建一个合适的 DHandler<T>实例。

Handler时的问题只接受 IBar<int>是编译器在推断类型参数时不会对参数使用可能的方法组转换。在 C# 3 和 C# 4 之间,类型推断肯定可以变得更强,并且确实有所改进 - 在一个非常相似的领域,尽管我永远记不起细节。

关于visual-studio-2010 - C# 编译器允许接口(interface)代替通用派生版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13905542/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com