微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 通用类型推理与多重实现的协变接口,如何解决?

考虑这个愚蠢的程序,什么都不做:
interface I<out T> { }
class A1 : I<A1> { }
class A2 : A1,I<A2> { }
class B1 { }
class B2 : B1,I<B2> { }
class C1 : I<A1> { }
class C2 : C1,I<A2> { }

static class Program
{
    static void f<T>(I<T> obj)
    {
    }

    static void Main()
    {
        f<A1>(new A2());
        f<A2>(new A2());
        f<B1>(new B2());
        f<B2>(new B2());
        f<A1>(new C2());
        f<A2>(new C2());
    }
}

这表明,A2和C2实现了I< A1>和I A2,并且B2实现了两个I B1.和I B2.

但是,将其修改

static void Main()
{
    f(new A2());
    f(new B2());
    f(new C2());
}

表示在第一行和第三行,f的泛型类型参数不能从传递的参数推断,但在第二行,它可以是.

我明白编译器在这里做什么,所以不需要解释.但是我该如何解决这个问题?有没有办法修改这个,以便我可以在基类和派生类上定义接口,但是在传递派生类时,还有类型推断工作?

我想到的是寻找一种方法来“隐藏”一个基类实现的接口,这样编译器就不会看到它们并使用它们,即使它们存在.但是,C#似乎没有提供这样的选择.

澄清:在我的愚蠢的示例程序中,A1将自己实现为通用类型参数.我确实有我的真实代码,但我也有类实现我与一个不同的通用类型的参数,并添加了C1和C2到我的示例代码为此原因.

解决方法

使用两个F变体(第二个仅用于调用一个的类型推断)和“继承”接口J继承自I,它不会像这样做:
using System;
using System.Threading;


interface I<out T>
{
    void Print();
}

interface J<out T> : I<T> { }

class A : I<C>
{
    void I<C>.Print()
    {
        Console.WriteLine("A: I<C>");
    }
}

class B {}

class C : B { }

class D1 : I<A>
{
    void I<A>.Print()
    {
        Console.WriteLine("D1: I<A>");
    }
}

class D2 : D1,J<B>
{
    void I<B>.Print()
    {
        Console.WriteLine("D2: I<B>");
    }
}

class D3 : D1,J<C>
{
    void I<C>.Print()
    {
        Console.WriteLine("D3: I<C>");
    }
}

class D4 : A,J<B>
{
    void I<B>.Print()
    {
        Console.WriteLine("D4: I<B>");
    }
}

static class Program
{
    static void f<T>(J<T> obj)
    {
        f((I<T>)obj);
    }

    static void f<T>(I<T> obj)
    {
        obj.Print();
    }

    static void Main()
    {

        f<A>(new D2());
        f(new D2());

        f(new D3());

        f(new D4());
        f<C>(new D4());

        Console.ReadKey();
    }
}

输出

D1: I<A>
D2: I<B>
D3: I<C>
D4: I<B>
A: I<C>

原文地址:https://www.jb51.cc/csharp/95693.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐