Mad*_*hik 73 c# casting explicit base-class derived-class
是否可以使用C#中的显式类型转换将基类对象分配给派生类引用?
我试过它,它会产生运行时错误.
Jon*_*eet 88
否.对派生类的引用实际上必须引用派生类的实例(或null).否则你会怎么期望它表现出来?
例如:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
Run Code Online (Sandbox Code Playgroud)
如果您希望能够将基类型的实例转换为派生类型,我建议您编写一个方法来创建适当的派生类型实例.或者再次查看继承树并尝试重新设计,这样您就不需要首先执行此操作.
Mic*_*ent 41
不,这是不可能的,因为将它分配给派生类引用就像是说"基类是派生类的完全能力替代,它可以完成派生类可以做的所有事情",这是不正确的,因为派生类一般提供比他们的基类更多的功能(至少,这是继承背后的想法).
您可以在派生类中编写构造函数,将基类对象作为参数,复制值.
像这样的东西:
public class Base {
public int Data;
public void DoStuff() {
// Do stuff with data
}
}
public class Derived : Base {
public int OtherData;
public Derived(Base b) {
this.Data = b.Data;
OtherData = 0; // default value
}
public void DoOtherStuff() {
// Do some other stuff
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您将复制基础对象并获取具有派生成员的默认值的功能齐全的派生类对象.这样你也可以避免Jon Skeet指出的问题:
Base b = new Base();//base class
Derived d = new Derived();//derived class
b.DoStuff(); // OK
d.DoStuff(); // Also OK
b.DoOtherStuff(); // Won't work!
d.DoOtherStuff(); // OK
d = new Derived(b); // Copy construct a Derived with values of b
d.DoOtherStuff(); // Now works!
Run Code Online (Sandbox Code Playgroud)
Mar*_*son 20
我遇到了这个问题并通过添加一个带有类型参数的方法并将当前对象转换为该类型来解决它.
public TA As<TA>() where TA : Base
{
var type = typeof (TA);
var instance = Activator.CreateInstance(type);
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
property.SetValue(instance, property.GetValue(this, null), null);
}
return (TA)instance;
}
Run Code Online (Sandbox Code Playgroud)
这意味着您可以在代码中使用它,如下所示:
var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1
Run Code Online (Sandbox Code Playgroud)
MEC*_*MEC 10
正如许多其他人所回答的那样.
当我需要使用基类型作为派生类型时,我在那些不幸的场合使用以下代码.是的,它违反了Liskov替代原则(LSP),是的,大多数时候我们赞成合成而不是继承.Markus Knappen Johansson的道具,其原始答案基于此.
这个代码在基类中:
public T As<T>()
{
var type = typeof(T);
var instance = Activator.CreateInstance(type);
if (type.BaseType != null)
{
var properties = type.BaseType.GetProperties();
foreach (var property in properties)
if (property.CanWrite)
property.SetValue(instance, property.GetValue(this, null), null);
}
return (T) instance;
}
Run Code Online (Sandbox Code Playgroud)
允许:
derivedObject = baseObect.As<derivedType>()
Run Code Online (Sandbox Code Playgroud)
由于它使用反射,因此它"昂贵".相应地使用.
Jes*_*ans 10
今天,我面临着同样的问题,我发现了一个简单而快速的解决问题的方法使用JsonConvert。
var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);
Run Code Online (Sandbox Code Playgroud)
在 c# 9.0 中,您可以尝试使用记录来实现此目的。它们具有复制所有字段的默认复制构造函数 - 无需对所有字段使用反射/构造函数。
public record BaseR
{
public string Prop1 { get; set; }
}
public record DerivedR : BaseR
{
public DerivedR(BaseR baseR) : base(baseR) { }
public string Prop2 { get; set; }
}
var baseR = new BaseR { Prop1 = "base prob" };
var derivedR = new DerivedR(baseR) { Prop2 = "new prop" };
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
109744 次 |
| 最近记录: |