Upcasting in .NET using generics - c#

So I've got a class like this:
public class A {
internal A(int i) { ... }
public int Foo { get; set; }
}
This class is then inherited by a bunch of generated classes, eg:
public class B : A {
...
}
The int based constructor isn't exposed to the inherited class (for design reasons I don't want it exposed). In my library which holds the definition for class A I've got a method like this:
public T Load<T>() where T : A {
//do some stuff, create an instance of T from an int, then return it
}
And then I'd use it like this:
B b = Helper.Load<B>();
Since the constructor I want to use isn't exposed to class B when I do typeof(T).GetConstructor(typeof(int)) I don't get the constructor back, so I want thinking that I'd do this:
return (T)new A(/*some int */);
But that gives me a runtime error System.InvalidCastException, that I can't cast a type A to type B.
How do I go about achieving this upcasting?

You can just use default constructors so you can instantiate objects of type T with the new() constraint. Then class A can have a virtual (or abstract to your liking) method that takes an int as an argument and initializes the object after the constructor has run.
public class A {
internal A() { }
internal Initialize(int i) { Foo = i; }
public int Foo { get; set; }
}
public class B : A {
internal B() { }
}
...
public T Load<T>() where T : A, new() {
var ret = new T();
ret.Initialize(i);
return ret;
}
If you intend some sort of factory pattern, you don't need to hesitate initializing parts of an object outside the constructor call as long as it is done before you return the object to the caller's control.

From what I understood, T derives from A, so you can't cast A to T.

You can't upcast A to B in your example, because:
return (T)new A(/*some int */);
Instantiates an A, which is not a B. Just because a "B is an A" does not mean "A is a B". You would have to first instantiate a B, cast it to an A, do what you want, and then upcast it back to a B.
I'm not sure if this is will compile, but you could try this:
T blah = new T(5); //this means your B will need to implement a int constructor
A blah2 = (A)blah;
//operate on A specific operations in blah2
T upcasted = (T)blah2;
//alternatively
T upcasted = blah2 as T;
Consider refactoring your contructor such that you initialize the integer as a property, instead of a parameter of the constructor. I strive to have default(no parameters) contructors so that generic code can instantiate the class easily.

You cant do this, change your design.

Related

Cannot read interface property from a subclass that implements it?

Apologies if this is duplicate, I'm not familiar enough with the correct terminology to know if this is asked elsewhere. I'm new to interfaces and am creating some sample code to see what kind of helpful things they can achieve.
I have a method that returns two possible classes that both implement the same interface. However, I can only access the properties from the parent class and not the sub-class, and have failed to find an explanation. I realise my entire approach may be flawed and will accept that advise also.
This is better explained with an example (NetFiddle) and questions...
using System;
public interface IAb
{
int Prop1 { get; set; }
}
public class A : IAb
{
public int Prop1 { get; set; }
}
public class B : A, IAb
{
public string Prop2 { get; set; }
}
public class Program
{
static class MyMethods
{
public static IAb CreateObject(Type t)
{
if (t == typeof(A))
{
return new A() {Prop1 = 123};
}
else
{
return new B() {Prop1 = 456, Prop2 = "Foo"};
}
}
}
public void Main()
{
IAb AorB = MyMethods.CreateObject(typeof(B));
Console.WriteLine(AorB.Prop1);
if (AorB is B)
{
// fails
// Console.WriteLine((B)AorB.Prop2); // 'IAb' does not contain a definition for 'Prop2'
// works
B newVar = (B)AorB;
Console.WriteLine(newVar.Prop2);
}
}
}
Based on the above:
Why does AorB.Prop1 work, but not AorB.Prop2 without an explicit cast?
Does the above mean that an interface should always be cast to a class before reading it's properties?
Is there a better way to specify the return type of the example method? The current approach feels error-prone because this (albeit unlikely code) would cause an error: var AorB = (B) MyMethods.CreateObject(typeof(A));
You may use pattern matching with is operator to make it more clear
IAb AorB = MyMethods.CreateObject(typeof(B));
Console.WriteLine(AorB.Prop1);
if (AorB is B b)
{
Console.WriteLine(b.Prop2);
}
Your failed line becomes correct after using right parenthesis
Console.WriteLine(((B)AorB).Prop2);
There is also no need to inherit B class from both A class and IAB interface. Since A already implements IAB, you can simply use public class B : A
Is there a better way to specify the return type of the example
method?
Make the CreateObject method generic and use constraints to restrict T type parameter to class, which implements IAb interface and has a parameterless constructor (this's what new() means exactly)
public static T CreateObject<T>() where T : IAb, new()
{
return new T { Prop1 = 123 };
}
and invoke it in the following way
IAb AorB = MyMethods.CreateObject<B>();
But in this case you can set only properties, defined in IAb interface, not the B class specific.
Why does AorB.Prop1 work, but not AorB.Prop2 without an explicit cast?
Because the property selector has precedence over the type cast. Just add parentheses:
Console.WriteLine(((B)AorB).Prop2);
Does the above mean that an interface should always be cast to a class before reading it's properties?
No.
Is there a better way to specify the return type of the example method? The current approach feels error-prone because this (albeit unlikely code) would cause an error: var AorB = (B) MyMethods.CreateObject(typeof(A));
You could use generics:
T CreateObject<T>() where T : new()
{
return new T();
}
However, that does not provide you with compile-time access to properties as in your example. You could slightly improve by providing versions of the method with appropriate constraints:
T CreateObject<T>() where T : IAb, new()
{
var result = new T();
result.Prop1 = 123;
return result;
}

Override at least one method

Let's suppose there is a following class:
public class foo{
internal virtual object M1(/*args*/){return null;}
internal virtual object[] M2(/*args*/){return null;}
public SomeStruct SomeMethod(){
return new SomeStruct
{
Obj = M1();
ObjArr = M2();
}
}
}
Using the following struct:
public class SomeStruct
{
public object Obj;
public object[] ObjArr;
}
Is there a way to make sure (preferably at compilation) to force either at least one method or exactly one method of class foo to be overriden?
Before anybody says it - I know it's possible to use one method and check if the result is array (or IEnumerable) and then assign it to the right field, but that takes more time then just running empty methods. I'm just wondering if it's possible to do it that way.
You could mark the methods abstract, and then you will be forced to implement both of the methods. This seems to be the most straightforward solution:
internal abstract object M1(/*args*/){return null;}
internal abstract object[] M2(/*args*/){return null;}
Another option, actually too complicated for this purpose, is to write a Roslyn code analyzer which will check the code and determines if it is valid.
As a side note: your fields should reside in the base class too. You could use generics if you want to make the types of them generic.
"No", basically. At least, not without writing your own custom code analyzer (perhaps via Roslyn), and considering what happens if X : foo overrides M1, and Y : X overrides M2.
You need to create a new method in your child class that hides the implementation of the base class, with the new return type. You cannot use virtual methods to overload a method like you're doing.Overloading of methods is done by changing the parameters, not the return type.
So either hide the parent method, in the child class, or create a method with another name.
Here is something that I can think of, just an example.
Run it here .Net Fiddle
using System;
public class a
{
public virtual object s(int a)
{
return a + 1;
}
}
public class b : a
{
public virtual object[] s(int a)
{
var arr = new object[]{a + 2};
return arr;
}
}
public class c : b
{
private a A = new a();
private b B = new b();
public c()
{
print(2);
}
public void print(int a)
{
var result = A.s(1);
Console.WriteLine("result : " + result);
var resultB = B.s(1);
//or resultB = base.s(1);
foreach (var r in resultB)
{
Console.WriteLine("result B : " + r);
}
}
}
public class Program
{
public static void Main()
{
c C = new c();
}
}

Using the constructor of the base class when creating new object of derived class?

Public class A
{
...
}
Public class B:A
{
...
}
Public class Prog
{
public static void Main()
{
A myA = new B();
}
}
If myA is an instance of A class, why I use B constructor, and how it differ from this:
A myA = new A();
also this code may be closer to this issue:
I know this may be very basic question, but I'm really confused.
You don't have to use the B constructor, only if you want an instance of B that inherits A.
You can also setup B so that is calls the constructor of A for you, eg:
public class A
{
public A()
{
}
}
public class B : A
{
public B() : base()
{
}
}
It all entirely depends on the implementation of your A and B classes and what you want to use them for.
Edit:
In light of your image, the reason you are calling like Vehicle c = new Car() is because the object you are actually creating is a Car but you still want or need to use aspects of the base class. Having this base class means you can have common properties between implementing classes.
For example:
public class Vehicle
{
public Vehicle()
{
}
public int NumberOfWheels { get; set; }
}
public class Car : Vehicle
{
public Car() : base()
{
NumberOfWheels = 4;
}
}
public class Motorbike : Vehicle
{
public Motorbike() : base()
{
NumberOfWheels = 2;
}
}
This case allows you to only define NumberOfWheels once and just set the value appropriately for the implementation you are writing. You can do the same thing with methods using virtual methods.
A myA = new B();
This is creating an object of type B. It is not creating an object of type A. However, you are casting the object to A. Casting in layterms essentially means you are saying 'View this object as if it were an A. Ignore the fact that it may be a B. Only show me methods and properties which were defined in the class A).
Note that you can re-cast it back to B, which does not change the object whatsoever:
B myB = (B)myA;
The difference between this:
A myA = new A();
and this:
A myA = new B();
Is that the first statement is creating a physical object of type A. Any overrides or new method/properties/fields defined in B will not be created. The second statement will create a physical object of type B, but to view it (even temporarily) as an A

Is it possibly to impose type constraints on a generic member of a class in an inheritance hierarchy?

I'm writing an application in C#, and am wrestling with its implementation of generics. I have an inheritance hierarchy that is mirrored by another inheritance hierarchy (Models and View Models) like so:
class A_Content { }
class B_Content : A_Content
{
public string Bar;
}
class C_Content : A_Content
{
public string Foo;
}
class A { public A_Content content; }
class B : A { }
class C : A { }
public class Test
{
IList<A> A_Collection = new List<A>();
public Test()
{
B b = new B();
C c = new C();
b.content = new B_Content();
c.content = new C_Content();
A_Collection.Add(b);
A_Collection.Add(c);
}
}
This works well enough, but doesn't enforce any type constraints on content, which leaves me casting it to the proper derived class every time I want to use it. I'd like to coax the compiler into enforcing the constraint that B objects only have B_Content content. My first cut at that was:
class A_Content { }
class B_Content : A_Content
{
public string Bar;
}
class C_Content : A_Content
{
public string Foo;
}
class A { }
class B : A { B_Content content; }
class C : A { C_Content content; }
public class Test
{
IList<A> A_Collection = new List<A>();
public Test()
{
B b = new B();
C c = new C();
A_Collection.Add(b);
A_Collection.Add(c);
}
}
This works nicely, but means that I can't access the common elements of content when all I have is a collection of As. What I'd really like to do is something like:
abstract class A_Content { }
class B_Content : A_Content
{
public string Bar;
}
class C_Content : A_Content
{
public string Foo;
}
abstract class A<T> { T content; }
class B : A<B_Content> { }
class C : A<C_Content> { }
public class Test {
IList<A<A_Content>> A_Collection = new List<A<A_Content>>();
public Test()
{
B b = new B();
C c = new C();
A_Collection.Add(b);
A_Collection.Add(c);
}
}
This, however, produces an error complaining that B cannot be implicitly converted into an A. I've tried adding an explicit cast to no avail. Is there some way to express the constraints I'm looking for more elegantly than the second model?
It's not entirely clear what you're after. Are you trying to make it so that every instance of A has a Content property whose type is A_Content, every B has a Content property that's a B_Content, and so on? If so, you can't do that and have B/C/etc. inherit from A. (not in a non-smelly way, anyway). The signature of A says that the Content property should be able to get (and, presumably, set) any valid value of A_Content. You cannot change the return type of a function or the type of a property or field in a derived class. You could use generics to basically defer the typing of the property all the way down to the usage of the class, but that syntax will be ugly and I'm not certain what it gets you.
For example, you could do this:
public class A<TContent> where TContent : A_Content
{
public TContent Content { get; set; }
}
public class B<TContent> : A<TContent> where TContent : B_Content
{
// nothing here, as the property is already defined above in A
}
public class C<TContent> : A<TContent> where TContent : C_Content
{
// nothing here, as the property is already defined above in A
}
But this means two things:
Anywhere you use A, B, or C you must specify the actual type of TContent (so A_Content, B_Content, etc.). Which is a pain
There is absolutely nothing stopping you from doing something like A<B_Content> (which is, in fact, essentially what B is in this case, since we've added nothing to the class).
In short, I think you need to drop back and punt and come up with a new design.
By the way
The reason your second example doesn't fly (with the List) is because you've told the list that it needs to contain A<A_Content>. Since B<B_Content> doesn't satisfy that, it won't work. This is a typical variance question and it confuses a lot of people. But consider this scenario (this code will not compile; it's intended to be demonstrative of the underlying reason):
List<A<A_Content>> list = new List<A<A_Content>>();
list.Add(new B()); // this seems OK so far, right?
A<A_Content> foo = list[0];
foo.content = new A_Content():
This would obviously break, since foo in reality is a B<B_Content>, so the runtime wouldn't let you set content equal to anything other than an instance of B_Content (or something that inherits from it), but the signature of the class means you should be able to assign anything that'sA_Content` or inherits from it.
You can use an interface for this, along with explicit implementation of the interface's member(s):
abstract class A_Content {}
class B_Content : A_Content {}
class C_Content : A_Content {}
interface IA
{
A_Content content { get; }
}
abstract class A<T> : IA
where T : A_Content
{
T content;
A_Content.content { get { return this.content; } }
}
class B : A<B_Content> {}
class C : A<C_Content> {}
Then you can make a List<IA> to hold a homogeneous collection of B and C objects.
In fact, with C# 4 and higher, you could make the interface generic and covariant; then you can implement the interface implicitly (as long as you use a property rather than a field):
interface IA<out T>
{
T content { get; }
}
abstract class A<T> : IA<T>
where T : A_Content
{
T content { get; set; }
}
class B : A<B_Content> {}
class C : A<C_Content> {}
Now, B still cannot be converted to A<A_Content>, but it can be converted to IA<A_Content>, so you can use a List<IA<A_Content>> to hold your homogeneous collection of objects.
Well, compiler produces an error, because indeed B cannot be converted into A<A_Content>.
This is because A<A_Content> is not a superclass of B. The parent class of B class is A<B_Content>.
I am afraid you need to stick to casting. It is needed here, because you have list of As.
If you really want to avoid casting (I am not sure why you would like to), you can try with dynamic dispatch.
You can try creating a List<dynamic> instead of List<A>.
You will need at least C# 4.0, though.
Hope I right undertsood your intention, so
having a collection like this
IList<A> means that you would like to have a collection of A objects with different implementation scenarios.
That property if the property of a base type. That means that base type has to expose methods/properties => so state and behavior primitives which the child classes has to make a concrete implementation.
Something like this:
class A_Content { public virtual string Bar {get;set;} }
class B_Content : A_Content
{
public override string Bar {get;set;};
}
class C_Content : A_Content
{
public override string Bar {get;set};
}
and somewhere in the code:
public Test()
{
B b = new B();
C c = new C();
A_Collection.Add(b);
A_Collection.Add(c);
//so
A_Collection[0].Bar // B::Bar
A_Collection[1].Bar //C::Bar
}
And you do not need to cast to real object. Simple OOP approach.

Inheritance: possible to change base reference to something else?

For example I have two classes, Base and Derived as shown below:
class Base
{
public string Name { get; set; }
public Base()
{
}
}
class Derived : Base
{
public Derived(Base b)
{
base = b; // doesn't compile, but is there any way to do something similar?
}
}
So that they behave like this:
Base b = new Base();
b.Name = "Bob";
Derived d = new Derived(b);
d.Name = "John";
// b.Name is now "John" also
Is this possible? I guess one way would be to keep the Base b reference in Derived and override Derived.Name to point to b.Name? Is there an easier way though, for example if I have like 50 properties to override?
class Derived : Base
{
Base b;
public override string Name
{
get { return b.Name; }
set { b.Name = value; }
}
public Derived(Base b)
{
this.b = b;
}
}
EDIT:
I guess another way to say it would be that I am creating a sort of wrapper for class Base. I am given an object of type Base and want to wrap it with class Derived but still keep Base's original public properties/methods/etc. I'm not sure if that makes it more clear or not.
I think from what you seem to be hinting at ( atleast from the edit - "I am creating a sort of wrapper for class Base"), you are looking at using the Decorator pattern:
http://en.wikipedia.org/wiki/Decorator_pattern
The decorator pattern can be used to extend (decorate) the
functionality of a certain object at run-time, independently of other
instances of the same class, provided some groundwork is done at
design time. This is achieved by designing a new decorator class that
wraps the original class.
Guess I'm confused
public BaseClass
{
public string Name { get; set; }
}
public DerivedClass : BaseClass
{
}
DerivedClass d = new DerivedClass();
d.Name = "Test";
BaseClass b = d as BaseClass;
print b.Name;
Output:
Test
The derived object inherits the methods, properties, fields and constructors(to some extend) of the base class, why override them when you can just use them.
Have you heard of the Decorator Pattern? http://en.wikipedia.org/wiki/Decorator_pattern
It's a way of dynamically modifying behavior at runtime by wrapping instances of classes within themselves like Russian Dolls. They all implement the same interface so to the user of the class the wrapped and unwrapped versions appear the same.
Interface IDecorator{
public void foo();
}
public class OuterDecorator:IDecorator{
private IDecorator _inner;
public OuterDecorator(IDecorator inner){
this.__inner = inner;
}
public void foo(){
this._inner.foo();
Console.Writeline("Hello from outer");
}
}
public class InnerDecorator:IDecorator{
public void foo(){
Console.Writeline("Hello from inner");
}
}
You can make a static function be a Factory Method.
public static IDecorator GetDecorator(){
var inner = new InnerDecorator();
var outer = new OuterDecorator(inner);
return outer;
}
And use it like so. The advantage is that the consumer of this class doesn't need to know the implementation details of the concrete class doing the work. Since both InnerDecorator and OuterDecorator implement the same interface they can be used interchangeably.
IDecorator d = OuterDecorator.GetDecorator();
d.foo();
//Output
//Hello from Inner
//Hello from Outer
here's some more information on the decorator pattern:
HeadFirst Design Patterns - start here
DoFactory

Categories