The purpose of using generic methods where generic is some base class - c#

Is there any purpose of using generic methods where T generic is base class? For example
class A: BaseClass
{
}
class B : BaseClass
{
}
class C
{
public T test<T> (T aa) where T : BaseClass
{
}
}
why do not just write in this way?
class C
{
public BaseClass test (BaseClass aa)
{
}
}
What gives us generic in this situation?

Your (non-generic) variant is returning an object of type BaseClass while the generic variant is returning an object of whatever T is (i.e. A or B or BaseClass).

Notice how your method returns an instance of T.
Using generics, this is valid:
A input = new A();
A output = c.test(input);
If we try and do the same with the version which just uses BaseClass:
A input = new A();
A output = c.test(input); // Error: can not assign instance of 'BaseClass' to 'A'
This is, obviously, because test returns an instance of BaseClass. Instead we have to write:
A input = new A();
A output = (A)c.test(input);
... and we don't have any compile-time guarantees that test actually returns an instance of A in this case, and not an instance of B.

Related

How can I get the properties of an inherited object when the parameter is declared as a base type?

I have a simple program that uses reflection to print out the properties and values of the supplied class.
class BaseClass
{
public string A
{
get { return "BaseClass"; }
}
}
class Child1 : BaseClass
{
public string Child1Name {
get { return "Child1"; }
}
}
class Child2 : BaseClass
{
public string Child2Name
{
get { return "Child2"; }
}
}
class Program
{
static void Main(string[] args)
{
var child1 = new Child1();
var child2 = new Child2();
SomeMethod(child1);
SomeMethod(child2);
Console.ReadKey();
}
static void SomeMethod(BaseClass baseClass)
{
PrintProperties(baseClass);
}
static void PrintProperties<T>(T entity)
{
var type = typeof(T);
foreach (var targetPropInfo in type.GetProperties())
{
var value = type.GetProperty(targetPropInfo.Name).GetValue(entity);
Console.WriteLine("{0}: {1}", targetPropInfo.Name, value);
}
Console.WriteLine("");
}
}
The problem is that it only prints out the BaseClass properties because I am using generics and passing in the BaseClass into the PrintProperties method.
Output:
A: BaseClass
A: BaseClass
How do I access the properties of the Child classes? I would like an output like:
A: BaseClass
Child1Name: Child1
A: BaseClass
Child2Name: Child2
The problem here is that you're using typeof(T) in PrintProperties, but the T in your example is BaseClass because that's the type of the parameter you give it from SomeMethod.
In your example, remove SomeMethod, call the PrintProperties method directly and it'll work.
A simpler way would be to use entity.GetType() instead of typeof(T). That way, no matter what the generic type is, you'll always get the true type of the object.
The issues here is that you're using generics and then pulling out the properties of the generic type's value.
Generics allow you to do some metacoding that's filled out at runtime (actually JIT-time) however the calls to generics deal with generic inferencing at compile time. Thus, because you call PrintProperties with a variable of type BaseClass, the T is always inferred to be BaseClass, not the actual runtime type.
There are two ways around this - one is to use the built in GetType() method that every object has.
var type = entity.GetType();
As this garunantees you'll have the runtime type to work with.
The other, for further cases of needing a perfect generic, is to pass to the generic method using a dynamic object, which allow the runtime to infer the generic type at runtime and thus get the exactly matching type:
static void SomeMethod(BaseClass baseClass)
{
PrintProperties((dynamic)baseClass);
}
typeof(T) will return you that specific type. This means when T is BaseClass you are only ever going to get properties related to it. It does not know about anything derived.
What you do instead is replace typeof(T) with entity.GetType(). GetType() returns you the actual type of the object instance.

Cast base type to inherited type with out Intilization

Is there anyway to cast\convert an object to an inherited type directly?
class Base
{
void Process()
{
Base obj = new Derived1();
}
}
class Derived1 : Base
{
}
class Derived2 : Base
{
}
How can i covert the object obj to type of Derived2 without intializing or creating a new instance of Derived2?
From your example you cannot change an object from Derived1 to Derived2. Your code is creating a new instance of Derived1 into an object type of Base this is fine as Derived1 will have the same signature as Base. However Base does not have the same signature as Derived1 and you are not able to convert to an inherited type. Although Derived1 has a base class of Base does not ensure the signatures are the same.
This is also true in user defined conversions using implicit or explicit operators. You cannot write your own conversions from a base class as this would provide multiple valid conversions.
The only way you can convert Base to Derived2 (or another derived class) is to create a new reference of Derived2 and copy your properties to this new class. However in a real world situation this is not only time consuming, but typically a flaw in your design process.
In most cases you invoke a method which returns an object of a specific type. For example Base (which really has not methods or properties) should define how the object acts and the common properties and methods for that object. Where Derived1 and Derived2 can build on this common signature. Your design here is quite flexible but in a common scenario you could essentially re-write your objects similar to the example below. Where you will notice there is not conversions required.
First define an interface for the base class. Although this is not required adds a concrete level of uniformity between your classes (again not required).
interface IBase
{
string Name { get; set; }
void DoWork();
}
This simply defines an interface with one property and one method. Next write your simply base class as:
class Base : IBase
{
string name = "Base Class: ";
public virtual string Name
{
get { return this.name; }
set { this.name = value; }
}
public virtual void DoWork()
{
//Base class does no work...
}
}
The base class Base inherits from IBase and implements both the method and the property from the interface. In this example I also marked the property and method as virtual https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx so any class that inherits from Base may override the member. So in this class the name is set (using a backing field) and has implemented the DoWork method which actually does nothing.
Next I define another class Derived1 which inherits from Base.
class Derived1 : Base
{
public override void DoWork()
{
this.Name = "Derived 1 did some work.....";
}
}
Now Derived1 inherits from Base and Base inherits the interface IBase. Base has defined the interface IBase and with the virtual keyword on both the method and the property. This means that Derived1 may override a member of Base (but doesnt have too)... The Derived1 class will now override the method DoWork and set the string Derived 1 did some work.... to the property Name.
We can then define a second class that inherits from Base as Derived2
class Derived2 : Base
{
string name;
public override string Name
{
get { return this.name; }
set { this.name = value; }
}
public override void DoWork()
{
this.Name = base.Name + " - Derived 2 did some work.....";
}
}
Just like before the new class Derived2 inherits from Base and in this instance is overriding both the property Name and the method DoWork however in this instance the do work method is access the property Name from the base class by using the base keyword. This essentially sets the name of Derived2 to the name of the base class Base and appends ' - Derived 2 did some work.....'.
Now this doesnt actually answer your question as you cant convert Derived2 to Derived or Derived2 to Base however provides the signature to build your classes against.
Now to use this in a real world we (as said before) execute methods or receive events that return our object type.
class Program
{
static void Main(string[] args)
{
var baseObj = getBase();
baseObj.DoWork();
Console.WriteLine("Base Name:" + baseObj.Name);
var d1 = getDerived1();
d1.DoWork();
Console.WriteLine("Derived 1 Name:" + d1.Name);
var d2 = getDerived2();
d2.DoWork();
Console.WriteLine("Derived 2 Name:" + d2.Name);
Console.ReadKey();
}
static IBase getBase()
{
return new Base();
}
static IBase getDerived1()
{
return new Derived1();
}
static IBase getDerived2()
{
return new Derived2();
}
}
As seen below we have 3 methods that return an instance of IBase these instances will all have matching signatures as they all inherit from the same interface. However in each method we are constructing new objects of different types. When the method DoWork is executed for each object the underlying methods are called on each object type.
Now this may be a long winded way of saying it can't be done but hopefully this shows you how you could achieve what are looking for by modifying how you define your objects.
Cheer
You cant do it, simply because Derived1 is not Derived2 (Derived1 != Derived2).
A good analogy would be, your base can be classified as a Fruit, and Derived1 and Derived2 can be Apple and Banana. In a bigger context, yes they're in the same categorization as a fruit. But you cant convert a banana to an apple and vise versa.
What you can do though is create your own converter, here is a quick mockup i created to get you started.
public static class ObjectConverter<T>
{
public static TTo Convert<TFrom, TTo>(TFrom value)
where TFrom : T
where TTo : T, new()
{
TTo result = new TTo(); // creates an instance of the target type
var baseProperties = value.GetType().GetProperties() // gets all properties
.Where(x => x.DeclaringType == typeof(T)); // based on target type
foreach (var prop in baseProperties)
{
prop.SetValue(result, prop.GetValue(value)); // sets value to the target
}
return result;
}
}
And consume like this.
Base item = new Derived1(); // base object
item.Age = 18; // properties existing on the base
item.Name = "Sasha";
Derived2 convertedItem = ObjectConverter<Base>.Convert<Derived1, Derived2>(item as Derived1);
I was looking for something like this. And the state design pattern fulfills it
http://www.codeproject.com/Articles/489136/UnderstandingplusandplusImplementingplusStateplusP

Call generics with base class gives cannot convert from base class to T

I have the following setup and it seems that my object cannot be converted to the generic type. While it is actually the base class. Why doesn't this work? It seems so logical to me.
public class AList<T> where T : A
{
void DoStuff(T foo)
{
}
void CallDoStuff()
{
DoStuff(new A()); // ERROR: Cannot convert A to T
}
}
public class A
{
}
The problem here is that the constraint says that T must be A or a class derived from A.
Now, when you instantiate AList with a concrete type, T is a very specific class. And if you didn't instantiate AList with A itself but with a subclass of it, T is a subclass of A.
You can't convert an instance with a runtime type of the base class to one of its subclasses, as it misses all the information that is being added by the subclass.
Example:
public class Animal
{
public int Foo { get; set; }
}
public class Cat : Animal
{
public int Bar { get; set; }
}
Derived d = new Base();
Would you expect that code to work? Surely not, because a Cat is also a Animal but a Animal is not a Cat.
If you would expect the above code to actually work, ask yourself what is supposed to happen when the following code is executed: d.Bar = 42;
Animal doesn't contain a definition for Bar.
The same is happening in your code - it's just a little bit more obscured with the generics in the game.
T could be also a class that derives from A so you can't put instance of A as a parameter of type T. Something like invoking method, that takes int with and argument that is of type object.
This is the same reason that is an object can not be converted to int implicitly.
The method expects a child class and you are passing the parent, so you need an explicit cast.
Because you are asking T to extend A. So you can replace T with A but not A with T.
if Cat : Animal it doesn't mean you can always convert an Animal to a Cat.
Try and use Activator to give you an instance of A from T because you know that T has to be A due to your constraint, so there isn't a need to use new A() anywhere as you have T, so you can just create an instance of T.
T obj = Activator.CreateInstance<T>();
DoStuff(obj);
Or do a cast of your object as other answers have mentioned, however this will not work in all cases.
T obj = (T)new A();
DoStuff(obj);

C#: Override generic method using class generic parameter

Why is this not possible?
abstract class A
{
public abstract T f<T>();
}
class B<T> : A
{
public override T f()
{
return default (T);
}
}
Errors:
does not implement inherited abstract member 'A.f<T>()'
no suitable method found to override
I know that the signature must be same, but from my point of view I see no reason what could possibly be wrong that this is forbidden.
Also I know that another solution is to make A generic, rather than its method, but it is not suitable for me for some reason.
This is not possible because those methods have different signatures. A.f is generic method and B.f is not (it merely uses class generic argument).
You can see this form caller perspective:
A variableA = new A();
variableA.f<int>();
B<int> variableB = new B<int>();
variableB.f();
B does not fulfil the contract of A.
A allows f to be called with any type parameter to return that type. B doesn't allow f to be called with a type parameter, and just returns the type of B's type parameter.
For example, say you had a B<int> and cast it to an A (which should be possible as it inherits from it). Then you called f<bool>() on it (which should be possible as it's an A). What then? The underlying B<int> doesn't have a method to call.
B b = new B<int>();
// This is legal as B inherits from A
A a = b;
// This is a legal call, but how does b handle it?
bool result = a.f<bool>();
In the case of your code
abstract class A
{
public abstract T f<T>();
}
class B<T> : A
{
public override T f()
{
return default (T);
}
}
what do you expect to be called in the below code
public void Foo(A myObj) {
myObj.f<DateTime>();
}
Foo(new B<int>());
There's no implementation for that method though the type contract (the abstract class A) clearly states that you need an implementation. So you can either implement or change the contract to use a type argument at the class level
abstract class A<T>
{
public abstract T f();
}
class B<T> : A<T>
{
public override T f()
{
return default (T);
}
}
does compile however it also limits f of course
Probably this is what you intend to do:
abstract class A
{
public abstract T f<T>();
}
class B<U> : A
{
public override T f<T>() //also needs to have a generic type parameter
{
throw new NotImplementedException();
}
public U f()
{
return f<U>();
}
}
The generic method type parameter and the generic class type parameter (here T and U) have no straightforward connection, i.e. T is not restricted to be U (or something) in the base class and you cannot change this restriction in the derived class.
abstract class A
{
public abstract T f<T>();
}
class B<T> : A
{
public override T f<T>()
{
return default (T);
}
}

C# Casting types from Interfaces

I want to create a set of classes that are very similar and can be cast to each other types. My idea was that I would create an Interface object and implement it through a base class. Then create additional classes that inherit from my base. I could then use the Interface to work with the common (base) methods and cast an object from the BASE object to a custom type.
interface ImyInterface {
}
public class MyBase : ImyInterface {
}
public class MyCustom1 : MyBase {
}
public class MyCustom2 : MyBase {
}
// in helper class
public static MyBase GetGeneralOjbect() {
// get a generic base object
return new MyBase();
}
// How I'm trying to use this
MyCustom1 obj = GetGeneralOjbect() as MyCustom1;
This seems to work except for the casting of the object statement. MyCustom1 is always null even though the static helper GetGeneralOjbect returns a good MyBase object. Maybe this can't be done or I'm not doing it correctly. Any input would be appreciated.
This is because you can cast a MyCustom1 or MyCustom2 to MyBase, but not necessarily the other way.
When you create a MyBase via MyBase b = new MyBase();, b is a MyBase but not a MyCustom2, so casting b to MyCustom2 will fail.
What you can do is:
MyBase b = new MyCustom2();
MyCustom2 c = b as MyCustom2();
What you can't do is:
MyBase b = new MyCustom2();
MyCustom1 c = b as MyCustom1();
The "as" keyword says "if this object which is statically typed as MyBase has a runtime type of MyCustom1, then give it back to me statically typed as MyCustom1; otherwise, give me a null reference". The object you are casting has a runtime type of MyBase, not MyCustom1, which is why you are getting a null reference.
Basically you can cast up an inheritance chain but not down it. Say you had the following class heirarchy:
public class A {
}
public class B : A {
}
public class C : B {
}
If you instantiated a new instance of type B you could cast it to A but not C.
Have you considered using Factory Pattern?
An instance of MyCustom1 can be used whenever an instance of MyBase is expected, but MyBase cannot be used when MyCustom1 is expected.

Categories

Resources