C# 如何在不强制转换的情况下引用具有不同类型的父变量?
我有这种情况C# 如何在不强制转换的情况下引用具有不同类型的父变量?,c#,casting,C#,Casting,我有这种情况 public class Base { public Basedef def; } public class A : Base { } public class B : A { public int GetBar() { return def.bar; } } public class BaseDef { } public class ADef : BaseDef { public int foo; } publi
public class Base
{
public Basedef def;
}
public class A : Base
{
}
public class B : A
{
public int GetBar()
{
return def.bar;
}
}
public class BaseDef
{
}
public class ADef : BaseDef
{
public int foo;
}
public class BDef : ADef
{
public int bar;
}
如您所见,方法B:GetBar()中有一个错误,因为def无法访问bar,但如果您
public int GetBar()
{
return (def as BDef).bar;
}
应该可以,但我想避免强制转换,如何使用在基类中创建的引用从定义中获取属性而不使用强制转换
为什么要避免强制转换?因为它容易出现运行时错误,并且更容易引入错误,所以我希望使用类型安全编码
我想做什么
public class Factory
{
public static Base<BaseDef> Create(BaseDef d)
{
if(d is BDef)
return new B(); //Error, can not convert B to Base<BaseDef>
}
}
public class Program
{
B instance = Factory.Create(new BDef()); //Error, can not convert to Base<BaseDef> to B
}
公共类工厂
{
公共静态基创建(BaseDef d)
{
如果(d是BDef)
返回新的B();//错误,无法将B转换为基
}
}
公共课程
{
B instance=Factory.Create(new BDef());//错误,无法将基转换为B
}
我正在寻找一个优雅的解决方案
再见 将Basedef设置为abstract类并将其上的bar设置为抽象属性有意义吗?将Basedef设置为abstract类并将其上的bar设置为抽象属性有意义吗?要有一个优雅的、不强制转换的解决方案,编译器需要知道
def
是GetBar()中的BDef
。这是一种实现这一目标的方法,我认为这对您的情况非常有效:
public class Base<T> where T : BaseDef
{
public T def { get; set; }
}
public class A<T> : Base<T> where T : ADef
{
public int GetFoo()
{
return def.foo; // this works, too
}
}
public class B : A<BDef>
{
public int GetBar()
{
return def.bar;
}
}
用法如下:
void Main()
{
Factory.Create(new BDef());
Factory.Create<B, BDef>(new BDef());
Factory.CreateAlternate<B, BDef>(new BDef());
}
void Main()
{
创建(新的BDef());
创建(新的BDef());
CreateAlternate(新的BDef());
}
我喜欢最后一个,因为只要不是问题,就不需要强制转换;如果简明调用代码非常有价值(因为可以推断泛型类型),则喜欢第一个。要有一个优雅的、不需要强制转换的解决方案,编译器需要知道def
是GetBar()中的BDef
。这是一种实现这一目标的方法,我认为这对您的情况非常有效:
public class Base<T> where T : BaseDef
{
public T def { get; set; }
}
public class A<T> : Base<T> where T : ADef
{
public int GetFoo()
{
return def.foo; // this works, too
}
}
public class B : A<BDef>
{
public int GetBar()
{
return def.bar;
}
}
用法如下:
void Main()
{
Factory.Create(new BDef());
Factory.Create<B, BDef>(new BDef());
Factory.CreateAlternate<B, BDef>(new BDef());
}
void Main()
{
创建(新的BDef());
创建(新的BDef());
CreateAlternate(新的BDef());
}
我喜欢最后一个,因为只要不存在问题,就没有强制转换,或者如果简明调用代码非常有价值(因为可以推断泛型类型),那么第一个就没有强制转换。使用强制转换进行转换是不安全的,因为您试图做的基本上不是类型安全的
有一个类a和一个类B是Base的子类,Base有一个对BaseDef的引用。BaseDef可以是ADef或BDef,您不知道是哪一个,当然不能从任何告诉B的信息中得知
但是如果使用泛型,您可以向B提供它需要知道的信息,即它的BaseDef引用实际上是BDef
public class Base<T> where T : BaseDef
{
public T def;
}
public class A<T> : Base<T> where T : ADef
{
}
public class B : A<BDef>
{
public int GetBar()
{
return def.bar;
}
}
公共类基类,其中T:BaseDef
{
公共T-def;
}
公共A类:基础,其中T:ADef
{
}
B级:A级
{
公共int GetBar()
{
返回def.bar;
}
}
使用cast执行此操作是不安全的,因为您尝试执行的操作基本上是不安全的
有一个类a和一个类B是Base的子类,Base有一个对BaseDef的引用。BaseDef可以是ADef或BDef,您不知道是哪一个,当然不能从任何告诉B的信息中得知
但是如果使用泛型,您可以向B提供它需要知道的信息,即它的BaseDef引用实际上是BDef
public class Base<T> where T : BaseDef
{
public T def;
}
public class A<T> : Base<T> where T : ADef
{
}
public class B : A<BDef>
{
public int GetBar()
{
return def.bar;
}
}
公共类基类,其中T:BaseDef
{
公共T-def;
}
公共A类:基础,其中T:ADef
{
}
B级:A级
{
公共int GetBar()
{
返回def.bar;
}
}
为什么要避免强制转换?因为它容易出现运行时错误,并且更容易引入错误,所以我希望使用类型安全编码
我不明白为什么cast容易出错,如果您不知道def
的RuntimeType
是什么,我会说您的设计是错误的
在我看来,您应该知道它的运行时类型
有一些变通办法
解决方案1:
public int GetBar()
{
if (def is BDef)
return ((BDef)def).bar;
return 0;//some default value
}
解决方案2:
介绍一个enum
说我是谁
public enum DefType
{
BaseDef = 0,
ADef =1,
BDef =2
}
public class BaseDef
{
public virtual DefType MyType
{
get{ return DefType.BaseDef; }
}
}
public class ADef
{
public override DefType MyType
{
get{ return DefType.ADef; }
}
}
然后像这样使用它
switch(def.MyType)
{
case DefType.ADef:
{
(ADef).foo;//you know who is this here right?
}
...
}
为什么要避免强制转换?因为它容易出现运行时错误,并且更容易引入错误,所以我希望使用类型安全编码
我不明白为什么cast容易出错,如果您不知道def
的RuntimeType
是什么,我会说您的设计是错误的
在我看来,您应该知道它的运行时类型
有一些变通办法
解决方案1:
public int GetBar()
{
if (def is BDef)
return ((BDef)def).bar;
return 0;//some default value
}
解决方案2:
介绍一个enum
说我是谁
public enum DefType
{
BaseDef = 0,
ADef =1,
BDef =2
}
public class BaseDef
{
public virtual DefType MyType
{
get{ return DefType.BaseDef; }
}
}
public class ADef
{
public override DefType MyType
{
get{ return DefType.ADef; }
}
}
然后像这样使用它
switch(def.MyType)
{
case DefType.ADef:
{
(ADef).foo;//you know who is this here right?
}
...
}
我假设您希望ADef继承自BaseDef,但您没有编写它,因此将BaseDef强制转换为BDef毫无意义……为什么要避免强制转换?如果没有虚拟方法或属性/reflection,您试图实现的目标是不可能的。我已经编辑了您的问题,假设您的意思是ADef:BaseDef
。如果不编辑你的问题背面,是的,我的意思是,谢谢你指出sriram,更新的问题,添加了为什么我要避免强制转换我假设你希望ADef继承自BaseDef,但你没有编写它,所以将BaseDef强制转换为BDef没有意义…你为什么要避免强制转换?如果没有虚拟方法或属性/reflection,您试图实现的目标是不可能的。我已经编辑了您的问题,假设您的意思是ADef:BaseDef
。如果不编辑你的问题背面,是的,我的意思是,感谢你指出sriram,更新的问题,添加了为什么我要避免casting否,因为bar是B的一个特定属性,想法是使用Def类创建a的实例,而Balso,a不应该使用自己的defno访问bar,因为bar是B的一个特定属性,想法是使用Def类创建A的实例,Balso,A不应该使用自己的defI访问bar。考虑到这一点,A可以使用其Def引用获取foo值?@joecabesas是的,我的解决方案支持这一点,因为编译器知道de