C# 继承把一个孩子传给另一个

C# 继承把一个孩子传给另一个,c#,inheritance,casting,C#,Inheritance,Casting,我有一个简单的结构:一个父母,两个不同的孩子 我有一个ChildA类型的对象objA,我想将其转换为ChildB。我天真的做法是: ChildA objA = new ChildA(); ChildB objB = (ChildB)objA; 但这不可能直接实现——为什么?这是因为我需要实现一些功能,还是因为我天真的方法是错误的 关于Casper,这是不可能的,因为objA引用的对象不是一个ChildB。换一种说法,这里有一个你正在尝试做的例子: string x = "hi"; Fil

我有一个简单的结构:一个父母,两个不同的孩子

我有一个ChildA类型的对象objA,我想将其转换为ChildB。我天真的做法是:

ChildA objA = new ChildA();

ChildB objB = (ChildB)objA;
但这不可能直接实现——为什么?这是因为我需要实现一些功能,还是因为我天真的方法是错误的


关于Casper,这是不可能的,因为objA引用的对象不是一个
ChildB
。换一种说法,这里有一个你正在尝试做的例子:

 string x = "hi";
 FileStream y = (FileStream) x;
它们都有一个共同的父类--
System.Object
,但它们是完全不同的类。如果您试图从
y
读取,您希望发生什么

假设您的
ChildB
类型具有特定于该类型的某个字段-在强制转换
objA
后,您希望该字段的值是多少

为什么要假装一个
ChildA
实际上是一个
ChildB
?您是否可以在父类中添加一个方法来满足您的需要?在
ChildA
中添加如下方法:

ChildB ToChildB()
var a = new ClassA() {Property1 = "test"};
ClassB b = a;

要执行适当的转换?

您不能,因为ChildA不是ChildB(您只能从ChildA或ChildB向上转换到父级,或从父级向下转换到ChildB或ChildA,在C#中没有旁转换)


如果您想使强制转换成为可能(这是一个值得商榷的尝试,但很好),您应该实现从ChildA到ChildB的强制转换操作符。

objA不是ChildB类型的,即使两者都是来自类父的“子级”。

您尝试做的事情不会起作用

您只能将objA装箱到它的基类(父类)或ChildA和ChildB可能实现的任何公共接口


想象一下,ChildB定义了一个名为Foo的方法。你的objA实例如何处理一个叫Foo的人?显然,它无法工作。

即使它们有一个父对象,也不可能简单地将一个对象强制转换为其他类型,因为它们可能有不同的接口

您需要实现ChildA(或ChildB)的显式或隐式运算符

在实现转换后,以下代码可以正常工作:

var a = new ClassA() {Property1 = "test"};
ClassB b = (ClassB)a;
Console.WriteLine(b.Property2); // output is "test"
在第一种情况下,您可以明确省略类型转换,并按如下方式编写:

ChildB ToChildB()
var a = new ClassA() {Property1 = "test"};
ClassB b = a;
最后,如果只想同步父类的属性,可以直接在父类中编写转换器:

class Parent
{
    public string ParentProperty { get; set; }
    public static T1 Convert<T1>(Parent obj) where T1 : Parent, new()   
    {
    var result = new T1();
    result.ParentProperty = obj.ParentProperty;
    return result;
    }
}
类父类
{
公共字符串ParentProperty{get;set;}
公共静态T1转换(父对象),其中T1:Parent,new()
{
var结果=新的T1();
result.ParentProperty=obj.ParentProperty;
返回结果;
}
}
使用(父母的A类和B类子女):

var a=new ClassA();
a、 ParentProperty=“test”;
ClassB=父级转换(a);
Console.WriteLine(b.ParentProperty);//输出为“测试”

ChildA
ChildB
是共享同一父项的不同类型。因此,您可以将
ChildA
ChildB
的实例视为它们的基础,
Parent
,但由于它们是不同的类型,您不能将一个转换为另一个

正如其他人所说,ChildA不是ChildB。如果ChildA和B具有相同的属性/功能,则应执行以下操作:

public class Parent{}
public class Child : Parent{}

Child objA = new Child();
Child objB = objA;

但我想这只是一个例子,你有一个真实的例子,为什么你想实现这样的目标?

我很确定我已经想出了一个方法来模拟这个,这在某个时候可能是有用的。即:

  • 从Dictionary或IDictionary继承,并在需要其他基础继承时实现它
  • 将属性存储在两个位置-字典和实字段
  • 保留第三个布尔字段,用于标记是否已设置实字段
  • 如果设置了实字段,则取实字段
  • 如果没有,则获取字典值(以及将其分配给实字段并标记)
  • 如果没有字典值,则将该属性视为不存在
  • 添加一个构造函数,该构造函数接受字典并使用字典中的值填充该字典
现在,您可以从这个基类继承一个CatLikeObject,并通过使用构造函数(将cat转换为字典)生成一个相同的DogLikeObject(它将吠叫而不是喵喵叫,但仍然称为“Puss”)

缺点?属性占用了更多的空间,很多类型安全性都转移到了运行时,更不用说可能会出现的任何性能损失(肯定会有一些)。优势?如果你需要暂时把猫当作狗来对待,你可以

public class CSharepointStoredResults : Dictionary<string, object>
{

    public CSharepointStoredResults(Dictionary<string, object> SourceDict = null) 
    {
        // Populate class dictionary from passed dictionary. This allows for some degree of polymorphism sideways.
        // For instance it becomes possible to treat one CSharepointStoredResults as another (roughly like treating
        // a cat as a dog
        foreach (string key in SourceDict.Keys) { this.Add(key, SourceDict[key]); }
    }

    public Type MyType 
    {
        get {
            if (!__MyType && !this.ContainsKey(bObj.GetPropertyNameFromExpression(() => this.MyType)))
            {
                // Neither a dictionary nor a field set
                // return the field
            }
            else if (!__MyType)
            {
                // There is a dictionary entry, but no volatile field set yet.
                __MyType = true;
                _MyType = this[bObj.GetPropertyNameFromExpression(() => this.MyType)] as Type;
            }
            else 
            {
                // Volatile value assigned, therefore the better source. Update the dictionary  
                this[bObj.GetPropertyNameFromExpression(() => this.MyType)] = _MyType;
            }
            return _MyType;
        }
        set {
            // Verify the value is valid...
            if (!(value.IsInstanceOfType(typeof(CSharepointStoredResults))))
                throw new ArgumentException("MyType can only take an instance of a CSharePointResults object");
            _MyType = value;
            this[bObj.GetPropertyNameFromExpression(() => this.MyType)] = value;
        }
    }
    private volatile Type _MyType;
    private volatile bool __MyType;
公共类CSharepointStoredResults:字典
{
公共CSharepointStoredResults(字典SourceDict=null)
{
//从传递的字典填充类字典。这允许某种程度的侧向多态性。
//例如,可以将一个CSharepointStoredResults视为另一个CSharepointStoredResults(大致类似于
//像狗一样的猫
foreach(SourceDict.Keys中的字符串键){this.Add(key,SourceDict[key]);}
}
公共类型MyType
{
得到{
如果(!\uuu MyType&!this.ContainsKey(bObj.GetPropertyNameFromExpression(()=>this.MyType)))
{
//既不是字典也不是字段集
//退场
}
else if(!\uuuuu MyType)
{
//有一个字典条目,但尚未设置易失性字段。
__MyType=true;
_MyType=this[bObj.GetPropertyNameFromExpression(()=>this.MyType)]作为类型;
}
其他的
{
//分配了Volatile值,因此是更好的源。请更新字典
this[bObj.GetPropertyNameFromExpression(()=>this.MyType)]=\u MyType;
}
返回_MyType;
}
设置{
//请验证该值是否有效。。。
public class Parent{}
public class Child : Parent{}

Child objA = new Child();
Child objB = objA;
public class CSharepointStoredResults : Dictionary<string, object>
{

    public CSharepointStoredResults(Dictionary<string, object> SourceDict = null) 
    {
        // Populate class dictionary from passed dictionary. This allows for some degree of polymorphism sideways.
        // For instance it becomes possible to treat one CSharepointStoredResults as another (roughly like treating
        // a cat as a dog
        foreach (string key in SourceDict.Keys) { this.Add(key, SourceDict[key]); }
    }

    public Type MyType 
    {
        get {
            if (!__MyType && !this.ContainsKey(bObj.GetPropertyNameFromExpression(() => this.MyType)))
            {
                // Neither a dictionary nor a field set
                // return the field
            }
            else if (!__MyType)
            {
                // There is a dictionary entry, but no volatile field set yet.
                __MyType = true;
                _MyType = this[bObj.GetPropertyNameFromExpression(() => this.MyType)] as Type;
            }
            else 
            {
                // Volatile value assigned, therefore the better source. Update the dictionary  
                this[bObj.GetPropertyNameFromExpression(() => this.MyType)] = _MyType;
            }
            return _MyType;
        }
        set {
            // Verify the value is valid...
            if (!(value.IsInstanceOfType(typeof(CSharepointStoredResults))))
                throw new ArgumentException("MyType can only take an instance of a CSharePointResults object");
            _MyType = value;
            this[bObj.GetPropertyNameFromExpression(() => this.MyType)] = value;
        }
    }
    private volatile Type _MyType;
    private volatile bool __MyType;