C# 传递实现的模板化类型:无法从实现转换为接口
有人能解释一下为什么这在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
名称空间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);
}
}
}