C # Inheritance dropping one child to another

I have this simple structure: 1 parent and two different childs.

public class Parent{} public class ChildA : Parent{} public class ChildB : Parent{} 

I have an objA object of type ChildA that I want to pass to ChildB. My naive approach says:

 ChildA objA = new ChildA(); ChildB objB = (ChildB)objA; 

But this is not possible directly - why? Is it because I need to implement some functions or because my naive approach is wrong?

Regards, Casper

+4
source share
8 answers

This is not possible because the objA object is not related to ChildB . In other words, here is an example of what you are trying to do:

  string x = "hi"; FileStream y = (FileStream) x; 

Both of them have a common parent element - System.Object - but they are completely different classes. What would you expect if you try to read from y ?

Suppose your ChildB type has some kind of field that is of this type - what would you expect this field value after casting objA ?

Why do you want to pretend that a ChildA is actually a ChildB ? Could you add a method to the parent class that does what you want? Add a method to ChildA as follows:

 ChildB ToChildB() 

to perform the corresponding conversion?

+10
source

It is not possible to simply drop one object of another type, even if it has one parent, because it may have different interfaces.

You need to implement an explicit or implicit ChildA (or ChildB) statement.

 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 }; } } 

or

 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; } } 

And after implementing the negotiation operators, the following code will work fine:

 var a = new ClassA() {Property1 = "test"}; ClassB b = (ClassB)a; Console.WriteLine(b.Property2); // output is "test" 

In the first case, you can omit the type conversion explicitly and write this:

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

And finally, if you want to synchronize only the properties of the parent class, you can write the converter directly to the parent:

 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; } } 

Usage (ClassA and ClassB childs of Parent):

 var a = new ClassA(); a.ParentProperty = "test"; ClassB b = Parent.Convert<ClassB>(a); Console.WriteLine(b.ParentProperty); // output is "test" 
+3
source

You cannot, because ChildA is not a childB (you can only upgrade from ChildA or ChildB to parent or drop from parent to ChildB or ChildA, there is no such thing as sidecasting in C #)

If you want to make the throw possible (a dubious attempt, but good), you must implement the translation operator from ChildA to ChildB.

+2
source

objA is NOT of type ChildB, even if both are "children" of the Parent class.

0
source

What you are trying to do will not work.

You can use only the objA object for the base class (parent) or for any common interface that ChildA and ChildB can implement.

Imagine for a moment that ChildB has defined a method called Foo. How would your objA instance deal with someone who called Foo? Obviously, this did not work.

0
source

ChildA and ChildB are different types that have the same parent. Thus, you can consider instances of both ChildA and ChildB as your base, Parent , but since they are different types, you cannot drop them to each other.

0
source

As others say, ChildA is not ChildB. If ChildA and B have the same properties / functions, then you should do:

 public class Parent{} public class Child : Parent{} Child objA = new Child(); Child objB = objA; 

But I think this is just an example, you have a real living example, why do you want to achieve something like this?

0
source

I'm sure I came up with a way to mimic this, which may be useful at some point. Namely:

  • Inherit from a dictionary or IDictionary and implement it if you need another basic inheritance
  • Save properties in two places - dictionary and real field
  • Store a third logical field that indicates whether the real field is still set
  • If a valid field is specified, take a valid field
  • If this is not the case, take the meaning of the dictionary (and also assign it to the real field and check)
  • If the value of the dictionary does not work, as if the property does not exist
  • Add a constructor that uses the dictionary and populates it with the values ​​from the dictionary

Now you can take the CatLikeObject, which inherits from this base class, and using the constructor (throwing the cat in the dictionary), generate an identical DogLikeObject (which will bark instead of the meow, but will still be called "Puss").

Disadvantages? Properties take up LOT more space, and greater type safety switches to runtime, not to mention any performance loss that may be (and there will definitely be some). Benefits? If you need to temporarily treat a cat as a dog, you can.

 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; 

}

0
source

All Articles