c#用子类类型的参数实现接口方法

Ang*_*gie 4 c# class-hierarchy

我有这个所需的类层次结构:

interface IClass
{
    string print(IClass item);
}

class MyClass : IClass
{
    // invalid interface implementation
    // parameter type should be IClass not MyClass
    string print(MyClass item)
    { return item.ToString(); }
}
Run Code Online (Sandbox Code Playgroud)

我尝试通过使用泛型类型解决接口实现问题,但没有成功:

interface IClass
{
    string print<T>(T item) where T : IClass;
}

class MyClass : IClass
{
    string print<T>(T item) where T : MyClass
    { return item.ToString(); }
}
Run Code Online (Sandbox Code Playgroud)

我该怎么办?

Meh*_*taş 12

使您的界面通用

interface IClass<T>  where T : IClass<T>
{
     string print(T item);
}

class MyClass : IClass<MyClass>
{
    public string print(MyClass item)
    { 
       return item.ToString(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,尽管这确实有效,但(1)令人困惑,并且(2)它不一定强制执行您希望强制执行的限制.有关此模式的一些想法,请参见http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx. (2认同)

Eri*_*ert 10

理解为什么这是非法的是有帮助的.您需要的功能是形式参数类型协方差,很少有语言提供它.(埃菲尔,我认为这是一个特色.)它不常见于语言中,因为它不安全!让我用一个例子来说明:

class Animal {}
class Lion : Animal { public void Roar() { } }
class Giraffe : Animal { }
interface IFoo { void M(Animal a); }
class C : IFoo
{
    public void M(Lion lion) { lion.Roar(); }
}
class P
{
    public static void Main()
    {
        IFoo foo = new C();
        foo.M(new Giraffe()); 
    }
}
Run Code Online (Sandbox Code Playgroud)

而我们只是长颈鹿咆哮.

如果你看一下所有这些类型的转换,可以合理进行非法的只有一个匹配C.M(Giraffe)IFoo.M(Animal).

现在,形式参数类型的逆变类型安全的,但它在C#中是不合法的,除非在一些非常有限的情况下.如果C#支持它,它不支持它,那么你可以安全地做这样的事情:

interface IBar { void M(Giraffe g); }
class D : IBar
{
    public void M(Animal animal) { ... }
}
class P
{
    public static void Main()
    {
        IBar bar = new D();
        bar.M(new Giraffe()); 
    }
}
Run Code Online (Sandbox Code Playgroud)

看看那里发生了什么?IFoo.M说"我可以带长颈鹿",CM说"我可以接受任何长颈鹿,因为事实上我可以接受任何动物".如果C#支持它,那将是类型安全的,但它只以两种方式支持它:

  • 逆变通用委托和接口转换.
  • 逆变方法将转换组转换为委托类型.

第一个示例是类型的表达式IComparable<Animal>可以IComparable<Giraffe>通过相同的逻辑分配给类型的变量:可以使用比较两个动物的方法,其中需要比较两个长颈鹿的方法.这是在C#4中添加的.

第二个例子是:

delegate void MyFunction(Giraffe g);
...
D d = new D();
MyFunction myfunc = d.M;
Run Code Online (Sandbox Code Playgroud)

同样,我们需要一个需要长颈鹿的功能,我们提供一个可以接受任何动物的功能.此功能已在C#2中添加.