Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Visual studio 2010 C#编译器允许接口代替泛型派生版本?_Visual Studio 2010_C# 4.0_.net 2.0 - Fatal编程技术网

Visual studio 2010 C#编译器允许接口代替泛型派生版本?

Visual studio 2010 C#编译器允许接口代替泛型派生版本?,visual-studio-2010,c#-4.0,.net-2.0,Visual Studio 2010,C# 4.0,.net 2.0,我对编译器中一些我不理解的行为有点困惑。我将其简化为以下代码示例: public interface IFoo { } public interface IBar<T> : IFoo { } public delegate void DHandler<T>(IBar<T> arg); public static class Demo { static void Garply<T>(DHand

我对编译器中一些我不理解的行为有点困惑。我将其简化为以下代码示例:

    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) { }
    }
公共接口IFoo{}
公共接口IBar:IFoo{}
公共代表无效DHandler(IBar arg);
公共静态类演示
{
静态void-Garply(DHandler处理程序){}
公共静态void dostufwithint()
{
加普利(装卸工);
}
静态void处理程序(IFoo arg){}
}
我的问题是,我不希望代码能够编译,但它确实可以。我不希望它编译,因为
DHandler
需要签名中的
IBar
,但是
Handler
方法声明
IFoo
,这不是
IBar
(尽管相反)。因此,
Handler
不是
DHandler
,因此它的委托不能用作
Garply
调用的参数

如果我将代码更改为read
Handler(IBar arg)
它将编译。如果我将其更改为read
Handler(IBar arg)
则不会。这两种行为都是我所期望的

提示这个问题的实际问题是,当签名是
Handler(IBar arg)
时,编译器会抱怨我需要显式指定
Garply
调用的类型参数。在本例中,这很平常,但在实际代码中,这将是一个真正的麻烦。我感到困惑,因为
Garply
的参数是一个带有签名
(IBar arg)
的方法,所以它的委托人将是
DHandler
,因此选择的
Garply
将毫无疑问地是
Garply
。但显然,编译器发现了一个歧义。它正在调查,这让我陷入了上面的困惑,我只能猜测,也许编译器在想“好吧,让Jason吃惊的是,我会接受一个
IFoo
,因为这个
IBar
,所以必须指定一个
T
,让我知道我应该把它编译成
IBar
,而不是
IFoo
”. 这也许可以解释为什么它需要类型参数。但是有人能解释一下吗?

这是委托差异,它是在C#2中引入的。这与C#4中引入的通用方差不同

这里有一个更简单的例子:

delegate void Foo(string x);    

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

    static void Bar(object y) {}
}
关键是我们可以从
Bar
方法创建
Foo
委托的实例,因为
Bar
只要给定任何
对象
,就可以工作。当调用
Foo
委托时,它将始终提供
string
引用,并且存在从
string
object
的引用转换。因此,如果我有:

Foo f = ...;
f("fred");
。。。该调用始终适用于
Bar

同样,在您的情况下,
Garply
使用
handler
进行的任何调用都肯定是对
handler
的有效调用-因此编译器很乐意创建一个适当的
DHandler
实例


Handler
只接受
IBar
时,问题在于编译器在推断类型参数时没有对参数使用可能的方法组转换。这是一个类型推断肯定会更强的领域,事实上它在一个非常相似的领域得到了改进,尽管我永远记不起细节——在C#3和C#4之间。

msdn.microsoft.com/en us/library/ms173174(v=vs.110)。aspxAh,因此委托问题是一个无关的红鲱鱼。在我的问题中,我假设该参数将使用委托协方差,但我应该预期反向方差。恐怕我从来没有实际使用过逆变或任何代理逆变,所以这对我来说是陌生的。我的坏-明天会预约让我的大脑旋转180度!至于我最初的问题——所以对于人类来说,类型是什么是显而易见的,我们可以想象编译器“应该”很容易看到它,但事实并非如此。公平地说,我会努力重新规划自己的道路。谢谢