我有这个简单的结构:1个父母和2个不同的孩子。
public class Parent{}
public class ChildA : Parent{}
public class ChildB : Parent{}
我有一个ChildA类型的对象objA,我想将其强制转换为ChildB。我天真的做法说:
ChildA objA = new ChildA();
ChildB objB = (ChildB)objA;
但这不是直接可能的 - 为什么?这是因为我需要实现一些功能还是因为我的天真方法是错误的?
问候,卡斯帕
答案 0 :(得分:10)
这是不可能的,因为objA
引用的对象是而不是 a ChildB
。换句话说,这是你要做的事情的一个例子:
string x = "hi";
FileStream y = (FileStream) x;
他们都有一个共同的父母 - System.Object
- 但他们是完全不同的类。如果您尝试阅读y
?
假设您的ChildB
类型有一些特定于该类型的字段 - 您希望该字段的值在投射objA
后会是什么?
为什么你想假装ChildA
实际上是ChildB
?你可以在父类中添加一个你想要的方法吗?在ChildA
中添加方法,如下所示:
ChildB ToChildB()
执行适当的转换?
答案 1 :(得分:3)
即使有一个父对象,也不可能简单地转换一个其他类型的对象,因为它可能有不同的接口。
您需要实现ChildA(或ChildB)的显式或implitic运算符。
class ClassA
{
public string Property1 { get; set; }
}
class ClassB
{
public string Property2 { get; set; }
public static implicit operator ClassB(ClassA classA)
{
return new ClassB() { Property2 = classA.Property1 };
}
}
或
class ClassA
{ {
public string Property1 { get; set; }
public static explicit operator ClassB(ClassA classA)
{
return new ClassB() { Property2 = classA.Property1 };
}
}
class ClassB
{
public string Property2 { get; set; }
}
在实现转换后,运算符跟随代码将正常工作:
var a = new ClassA() {Property1 = "test"};
ClassB b = (ClassB)a;
Console.WriteLine(b.Property2); // output is "test"
在第一种情况下,您可以省略明确的类型转换并像这样写:
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;
}
}
使用(Parent的ClassA和ClassB子级):
var a = new ClassA();
a.ParentProperty = "test";
ClassB b = Parent.Convert<ClassB>(a);
Console.WriteLine(b.ParentProperty); // output is "test"
答案 2 :(得分:2)
你不能因为ChildA不是ChildB(你只能从ChildA或ChildB转发到Parent,或者从Parent转发到ChildB或ChildA,在C#中不存在侧播)
如果你想使演员成为可能(这是一个值得怀疑的努力,但你应该),你应该实现从ChildA到ChildB的演员操作。
答案 3 :(得分:0)
objA是ChildB类型的 NOT ,即使两者都是来自Parent类的“children”。
答案 4 :(得分:0)
你要做的事情是行不通的。
你只能对它的基类(Parent)或者ChildA和ChildB可能实现的任何公共接口进行objA。
想象一下,ChildB定义了一个名为Foo的方法。你的objA实例如何处理调用Foo的人?显然它不起作用。
答案 5 :(得分:0)
ChildA
和ChildB
是共享同一父级的不同类型。因此,您可以将ChildA
和ChildB
的实例视为其基础Parent
,但由于它们是不同类型,因此您无法将其中一个转换为另一个。
答案 6 :(得分:0)
正如其他人所说,ChildA不是ChildB。如果ChildA和B具有相同的属性/功能,那么您应该这样做:
public class Parent{}
public class Child : Parent{}
Child objA = new Child();
Child objB = objA;
但我猜这只是一个例子,你有一个真实的例子,为什么你想要达到这样的目的?
答案 7 :(得分:0)
我非常确定我已经想出了一种模拟这种方法的方法,这在某些方面可能很有用。即:
现在你可以使用继承自这个基类的CatLikeObject,并使用构造函数(将cat转换为Dictionary),生成一个相同的DogLikeObject(它将吠叫而不是喵喵,但仍被称为&#34; Puss& #34;。)
缺点?属性占用了更多的空间,并且很多类型的安全性转移到运行时,更不用说可能存在的任何性能损失(并且肯定会有一些)。好处?如果您需要暂时将猫视为狗,您可以。
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;
}