Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/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
C# 传递实现的模板化类型:无法从实现转换为接口_C#_Generics - Fatal编程技术网

C# 传递实现的模板化类型:无法从实现转换为接口

C# 传递实现的模板化类型:无法从实现转换为接口,c#,generics,C#,Generics,有人能解释一下为什么这在C中是不正确的吗 名称空间a { 甲级公共课 { T1-mT1; 公共T1类型1 { 获取{return mT1;} } } 公共类IOForClassA { 公共接口输出 { void OutputFunction(); } 公共静态无效输出(ClassA aClassA_,无输出功能) { aClassA_WithOutputCapabilities.Type1.OutputFunction(); } } } 名称空间 { 公共B类 { 公共类OutputableCl

有人能解释一下为什么这在C中是不正确的吗

名称空间a
{
甲级公共课
{
T1-mT1;
公共T1类型1
{
获取{return mT1;}
}
}
公共类IOForClassA
{
公共接口输出
{
void OutputFunction();
}
公共静态无效输出(ClassA aClassA_,无输出功能)
{
aClassA_WithOutputCapabilities.Type1.OutputFunction();
}
}
}
名称空间
{
公共B类
{
公共类OutputableClassA:NamespaceA.IOForClassA.ICanOutput
{
公共void输出函数()
{
}
}
公共类别B()
{
NamespaceA.ClassA aOutputableA=新的NamespaceA.ClassA();
NamespaceA.IOForClassA.Output(aOutputableA);
}
}
}
这将导致编译错误:

参数1:无法从“NamespaceA.ClassA”转换为NamespaceA.ClassA

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


我试图允许用户创建他/她想要的任何类型的ClassA。然而,如果他们希望ClassA是“可输出的”,那么它的模板类型必须实现一个特定的接口。

您遇到了一个问题。基本上,只有接口才能允许泛型类型具有更派生的类型,并且只有在使用in/out关键字(在链接的文章中概述)显式指定泛型类型时才允许

在阅读代码时,您似乎希望在不知道类的类型的情况下调用类的已知命名成员,这可能更适合。不过,您可能需要稍微更改一下设计

namespace NamespaceA
{
    public class ClassA<T1> where T1 : IOForClassA.ICanOutput
    {
        T1 mT1;
        public T1 Type1
        {
            get { return mT1; }
        }
    }

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

        public static void Output<T>(ClassA<T> aClassA_WithOutputCapabilities) where T : IOForClassA.ICanOutput
        {
            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);
        }
    }
}
名称空间a
{
公共类ClassA,其中T1:IOForClassA.I输出
{
T1-mT1;
公共T1类型1
{
获取{return mT1;}
}
}
公共类IOForClassA
{
公共接口输出
{
void OutputFunction();
}
公共静态无效输出(ClassA aClassA_WithOutputCapabilities),其中T:IOForClassA.ICanOutput
{
aClassA_WithOutputCapabilities.Type1.OutputFunction();
}
}
}
名称空间
{
公共B类
{
公共类OutputableClassA:NamespaceA.IOForClassA.ICanOutput
{
公共void输出函数()
{
}
}
公共类别B()
{
NamespaceA.ClassA aOutputableA=新的NamespaceA.ClassA();
NamespaceA.IOForClassA.Output(aOutputableA);
}
}
}

OutputableClassA
源自
ICanOutput
。但这并不意味着
ClassA
也源自
ClassA
。这就是你的代码不起作用的原因


链接可能会有所帮助。

@syazdani认为这是一个协方差问题是正确的(他链接到了一篇有用的文章),但他的示例没有使用协方差,这将实现您所寻找的。虽然他的答案是正确的(并且可能更可取,因为它有一个额外的好处,即在您需要时将实际类型带入
输出
方法中,我想我会向您展示如何使用协变接口来实现这一点,以防它在您可能使用它们的任何其他情况下对您有所帮助:

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);
        }
    }
}
名称空间a
{
公共接口IClassA
{
T1类型1{get;}
}
A类公共课:IClassA
{
T1-mT1;
公共T1类型1
{
获取{return mT1;}
}
}
公共类IOForClassA
{
公共接口输出
{
void OutputFunction();
}
公共静态无效输出(不带输出功能的IClassA aClassA_)
{
aClassA_WithOutputCapabilities.Type1.OutputFunction();
}
}
}
名称空间
{
公共B类
{
公共类OutputableClassA:NamespaceA.IOForClassA.ICanOutput
{
公共void输出函数()
{
}
}
公共类别B()
{
NamespaceA.ClassA aOutputableA=新的NamespaceA.ClassA();
NamespaceA.IOForClassA.Output(aOutputableA);
}
}
}

“我试图允许用户创建他/她想要的任何类型的ClassA。但是,如果他们希望ClassA是“可输出的”,其模板类型必须实现特定的接口。”--因此,从这个解决方案来看,这是不可能的,因为上面演示的ClassA必须使用IOForClassA.ICANUPPUT类型进行模板化
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);
        }
    }
}