传递实现的模板类型:不能从实现转换为接口 [英] Passing implemented templated types: cannot convert from implementation to interface

查看:97
本文介绍了传递实现的模板类型:不能从实现转换为接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 命名空间命名空间A 
{
公共类ClassA< T1>
{
T1 mT1;
public T1 Type1
{
get {return mT1; }



public class IOForClassA
{
public interface ICanOutput
{
void OutputFunction();


public static void Output(ClassA< ICanOutput> aClassA_WithOutputCapabilities)
{
aClassA_WithOutputCapabilities.Type1.OutputFunction();



$ b命名空间命名空间B
{
public class ClassB
{
public class OutputableClassA: NamespaceA.IOForClassA.ICanOutput
{
public void OutputFunction()
{
}
}
public ClassB()
{
NamespaceA.ClassA< OutputableClassA> aOutputableA = new NamespaceA.ClassA< OutputableClassA>();
NamespaceA.IOForClassA.Output(aOutputableA);
}
}
}

这将导致编译错误:

参数1:无法从'NamespaceA.ClassA'<NamespaceB.ClassB.OutputableClassA>转换为NamespaceA.ClassA<NamespaceA。 IOForClassA.ICanOutput>



...但NamespaceB.ClassB.OutputableClassA实现NameSpaceA.IoForClassA.ICanOutput,所以我不明白为什么这是一个问题.. 。



我试图让用户创建他/她希望的任何类型的ClassA。但是,如果他们希望ClassA是可输出的,它的模板类型必须实现特定的接口。关于它是一个协变问题(他链接到一篇有用的文章),但他的例子不使用协变,这将实现你正在寻找的东西。虽然他的回答是正确的(并且可能是可取的,因为它具有带来实际类型的附加好处,以便您在需要时将 Output 方法引入),我想我会告诉你你可以如何使用协变接口来做到这一点,以防在任何其他情况下使用它们:

  namespace NamespaceA 
{
public interface IClassA< out T1>
{
T1 Type1 {get;}
}

public class ClassA< T1> ;:IClassA< T1>
{
T1 mT1;
public T1 Type1
{
get {return mT1;}
}
}

public class IOForClassA
{
public interface ICanOutput
{
void OutputFunction();
}

public static void Output(IClassA< ICanOutput> aClassA_WithOutputCapabilities)
{
ClassA_WithOutputCapabil ities.Type1.OutputFunction();




命名空间命名空间B
{
public class ClassB
{
public class OutputableClassA: NamespaceA.IOForClassA.ICanOutput
{
public void OutputFunction()
{
}
}
public ClassB()
{
NamespaceA.ClassA< OutputableClassA> aOutputableA = new NamespaceA.ClassA< OutputableClassA>();
NamespaceA.IOForClassA.Output(aOutputableA);
}
}
}


Can someone explain to me why this is incorrect in C#:

namespace NamespaceA
{
    public class ClassA<T1>
    {
        T1 mT1;
        public T1 Type1
        {
            get { return mT1; }
        }
    }

    public class IOForClassA
    {
        public interface ICanOutput
        {
            void OutputFunction();
        }

        public static void Output(ClassA<ICanOutput> aClassA_WithOutputCapabilities)
        {
            aClassA_WithOutputCapabilities.Type1.OutputFunction();
        }
    }
}

namespace NamespaceB
{
    public class ClassB
    {
        public class OutputableClassA : NamespaceA.IOForClassA.ICanOutput
        {
            public void OutputFunction()
            {
            }
        }
        public ClassB()
        {
            NamespaceA.ClassA<OutputableClassA> aOutputableA = new NamespaceA.ClassA<OutputableClassA>();
            NamespaceA.IOForClassA.Output(aOutputableA);
        }
    }
}

This will result in a compile error of:

Argument 1: cannot convert from 'NamespaceA.ClassA"<"NamespaceB.ClassB.OutputableClassA">" to NamespaceA.ClassA"<"NamespaceA.IOForClassA.ICanOutput">"

... but NamespaceB.ClassB.OutputableClassA implements NameSpaceA.IoForClassA.ICanOutput, so I don't see why this is a problem...

I am trying to allow a user to create a ClassA of any type he/she wishes. However, if they wish that ClassA to be "outputable" its templated type must implement a specific interface.

解决方案

@syazdani is correct about it being a covariance problem (and he links to a useful article), but his example doesn't then use covariance, which would achieve what you are looking for. Although his answer is correct (and likely preferrable as it has the added benefit of bringing along the actual type in case you need it into the Output method, I figured I would show you how you could also do this with a covariant interface in case it helps you in any other case where you may use them:

namespace NamespaceA
{
    public interface IClassA<out T1>
    {
        T1 Type1 { get; }
    }

    public class ClassA<T1> : IClassA<T1>
    {
        T1 mT1;
        public T1 Type1
        {
            get { return mT1; }
        }
    }

    public class IOForClassA
    {
        public interface ICanOutput
        {
            void OutputFunction();
        }

        public static void Output(IClassA<ICanOutput> aClassA_WithOutputCapabilities)
        {
            aClassA_WithOutputCapabilities.Type1.OutputFunction();
        }
    }
}

namespace NamespaceB
{
    public class ClassB
    {
        public class OutputableClassA : NamespaceA.IOForClassA.ICanOutput
        {
            public void OutputFunction()
            {
            }
        }
        public ClassB()
        {
            NamespaceA.ClassA<OutputableClassA> aOutputableA = new NamespaceA.ClassA<OutputableClassA>();
            NamespaceA.IOForClassA.Output(aOutputableA);
        }
    }
}

这篇关于传递实现的模板类型:不能从实现转换为接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆