C# 继承泛型类时的多态性 让我们考虑有一个抽象基类和一个或多个子类: public abstract class BaseInnerClass { public int Id { get; set; } } public class ConcreteInnerClass : BaseInnerClass { public string Name { get; set; } }
然后,假设有一个泛型抽象类具有上述抽象类类型的属性:C# 继承泛型类时的多态性 让我们考虑有一个抽象基类和一个或多个子类: public abstract class BaseInnerClass { public int Id { get; set; } } public class ConcreteInnerClass : BaseInnerClass { public string Name { get; set; } },c#,C#,然后,假设有一个泛型抽象类具有上述抽象类类型的属性: public abstract class GeneriAbstractTestClass<T> where T : BaseInnerClass { public T InnerClass { get; set; } } 这两个作业有什么区别?这与抽象类无关。一个更简单的例子是 List<BaseInnerClass> base = new List<ConcreteInnerClass>
public abstract class GeneriAbstractTestClass<T> where T : BaseInnerClass
{
public T InnerClass { get; set; }
}
这两个作业有什么区别?这与抽象类无关。一个更简单的例子是
List<BaseInnerClass> base = new List<ConcreteInnerClass>
如果您想要的是可能的,那么以下方法将起作用:
GeneriAbstractTestClass<BaseInnerClass> genericClass = new ConcreteTestClass();
genericClass.InnerClass = new EvilConcreteInnerClass(); // OK, because the compiler sees `T` as `BaseInnerClass`
GeneriAbstractTestClass genericClass=new-ConcreteTestClass();
genericClass.InnerClass=新的InnerClass();//好的,因为编译器将'T'视为'BaseInnerClass'`
genericClass
变量指向其T
泛型参数为ConcreteInnerClass
的对象,因此将指定给属性将导致运行时异常。实际上。你可以这样做。但您需要使用协变out Tgeneric指定接口,因为进行这些强制转换是类型安全的
示例
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
var a = new Generic<Concrete>();
IGeneric<Base> c = new Generic<Base>();
c = a;
}
}
public interface IGeneric<out T> where T: Base
{
T Inner { get; }
}
public class Generic<T> : IGeneric<T>
where T : Base
{
public T Inner { get; set; }
}
public class Concrete : Base
{
}
public class Base
{
}
}
名称空间控制台测试
{
班级计划
{
静态void Main(字符串[]参数)
{
var a=新的泛型();
IGeneric c=新的通用();
c=a;
}
}
公共接口IGeneric,其中T:Base
{
T内部{get;}
}
公共类泛型:IGeneric
其中T:Base
{
公共T内部{get;set;}
}
公共级混凝土:基础
{
}
公共阶级基础
{
}
}
如果委托指定了协变输出通用模板,则委托也不受限制
这意味着只要您使用只读泛型属性,您想要的强制转换就可以了。所以,正如@Kapol所说,并为您提供了一个示例,说明为什么允许属性上的setter或将T传递到函数中是不安全的
摘要
如果要使用这些类型的强制转换,请使用只读接口。简单地说,generabstracttestclass
不是generabstracttestclass
,反之亦然,就像列表一样-不确定这是否算是重复,但它非常接近。我认为阅读它会对你有所帮助:类不能是协变的,这就是问题所在。我同意,但这只是用C#设计的。没别的了。例如,C++中,可以使用协和来创建协变类,但这不是C++。我认为,更广泛地说,C++语法是有用的。
List<BaseInnerClass> base = new List<ConcreteInnerClass>
public class EvilConcreteInnerClass : BaseInnerClass
{
}
GeneriAbstractTestClass<BaseInnerClass> genericClass = new ConcreteTestClass();
genericClass.InnerClass = new EvilConcreteInnerClass(); // OK, because the compiler sees `T` as `BaseInnerClass`
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
var a = new Generic<Concrete>();
IGeneric<Base> c = new Generic<Base>();
c = a;
}
}
public interface IGeneric<out T> where T: Base
{
T Inner { get; }
}
public class Generic<T> : IGeneric<T>
where T : Base
{
public T Inner { get; set; }
}
public class Concrete : Base
{
}
public class Base
{
}
}