我有这种情况
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;
}
应该可以工作,但是我想避免强制转换,如何使用在Base类中创建的引用从定义中获取属性而不使用强制转换?
为什么要避免使用强制转换?因为容易出现运行时错误而且更容易引入错误,我想要类型安全的编码。
我想做什么
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
}
我正在寻找一个优雅的解决方案
再见!
答案 0 :(得分:2)
为了拥有一个优雅的,不流畅的解决方案,编译器需要知道def
中的BDef
是GetBar()
。这是一种方法,我认为这将适合您的情况:
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;
}
}
(顺便说一句,您应该使用公共属性,而不是公共字段。请参阅Honestly, what's the difference between public variable and public property accessor?了解原因。)
更新:您的Factory
方法可能看起来像其中之一:
public static Base<T> Create<T>(T d) where T : BaseDef
{
if(typeof(T) == typeof(BDef))
return (Base<T>)(object)new B();
else
return null;
}
public static T Create<T, U>(U d) where T : Base<U> where U : BaseDef
{
T result;
if (typeof(T) == typeof(B))
result = (T)(object)new B();
else
throw new NotImplementedException();
result.def = d;
return result;
}
public static T CreateAlternate<T, U>(U d) where T : Base<U>, new() where U : BaseDef
{
return new T { def = d };
}
用过:
void Main()
{
Factory.Create(new BDef());
Factory.Create<B, BDef>(new BDef());
Factory.CreateAlternate<B, BDef>(new BDef());
}
我喜欢最后一个因为没有转换,只要new()
constraint不是问题,或者第一个如果简洁的调用代码非常有价值(因为可以推断泛型类型)。
答案 1 :(得分:1)
使用演员表进行此操作并不安全,因为您尝试做的事情从根本上说并非类型安全。
你有一个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;
}
}
答案 2 :(得分:1)
为什么要避免使用强制转换?因为容易出现运行时错误而且更容易引入错误,我想要类型安全的编码。
我不明白为什么演员阵容容易出错,如果你不知道RuntimeType
的{{1}}是什么,我会说你的设计是错的。
在我看来,你应该知道它的运行时类型是什么。
有解决方法
解决方法1:
def
解决方法2:
引入public int GetBar()
{
if (def is BDef)
return ((BDef)def).bar;
return 0;//some default value
}
说enum
。
who am I
然后像
一样使用它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; }
}
}
答案 3 :(得分:0)
创建一个抽象类的Base并在其上设置一个抽象属性是否有意义?