How to return generic abstract class? - c#

I have something like this:
abstract class BaseClass<T>
{
protected BaseClass(){}
}
class Class1 : BaseClass<Class1>
{
public static Class1 Instance = new Class1();
private Class1(){}
}
class Class2 : BaseClass<Class2>
{
public static Class2 Instance = new Class2();
private Class2(){}
}
...
public BaseClass<T> Method<T>(int z) where T: BaseClass<T>
{
switch(z)
{
case 1:
return Class1.Instance;
case 2:
return Class2.Instance;
}
}
That is very important that those classes cannot be instantiated since their construstors are private so we cannot do like
public BaseClass<T> Method<T>(int z) where T: BaseClass<T>, new()
How can I use abstract class as return type ?? I just can not work this out. Would appreciate for any assisstance here.

It sounds to me like you can't really have the method be generic. For instance, what would happen if I called:
BaseClass<Class1> foo = Method<Class1>(2);
You need a single point of truth - either the type argument, or the normal argument. You can make it the method argument by having a non-generic base class (either by making the existing base class non-generic, or introducing a non-generic base class to that). Change the return type of Method to this non-generic base class.

abstract class BaseClass<T>
{
public abstract T Instance { get; }
protected BaseClass(){}
}
maybe? You can't inherit static stuff I believe...
On a closer look... I don't think what you are trying to do is even possible... what are you trying to do anyways?
A type constraint is a type constraint. You are trying to change the type constraint in the method kind of. which obviously doesn't work, and shouldn't work. I think you need to think of a different way of attacking your problem. Whatever it is...

Take a look at the factory pattern. Your factory can have a method on it to get the instance. The first time it's called, it creates the instance. On subsequent calls, it can return the already-created instance.

Related

Using static method from generic class

I have problem as above. My code:
public abstract class BaseFactory<T> where T: class
{
protected static dbModelContainer context = new dbModelContainer();
public static int UpdateDataBase_static()
{
return context.SaveChanges();
}
}
and my question is how can I call
BaseFactory.UpdateDataBase_static();
instead of:
BaseFactory<SomeClass>.UpdateDataBase_static();
Any ideas?
You can't, because there is no such method. The closest is to have a non-generic base that the generic class inherits from. Then you can have a method there that doesn't depend on the parameterising type.
To call BaseFactory.UpdateDataBase_static(); you need a class BaseFactory. Inherite the generic BaseFactory<T> from it.
public abstract class BaseFactory
{
protected static dbModelContainer context = new dbModelContainer();
public static int UpdateDataBase_static()
{
return context.SaveChanges();
}
}
public abstract class BaseFactory<T>:BaseFactory where T: class
{
....
}
You don't.
You always need to supply the generic type arguments when accessing a class, even though you aren't using that type argument in your method. Since you don't actually use the generic type in the method it means you could move that method out of that class, and into one that isn't generic, but for as long as it's in that class you'll need to supply the generic argument.
It's not possible to do exactly what you're asking, but since the method doesn't use T at all, you can just use BaseFactory<object>.UpdateDataBase_static(); without specifying any particular class.
But as an editorial comment, in general a method in a generic class that never uses the generic parameter probably shouldn't be there.

Can the type of the current class be used as the value of a generic type parameter?

Can something like this be accomplished using C#?
public abstract class BaseClass
{
public abstract IInterface<T> CreateEditor() where T: the_actual_type_of_this_instance;
}
Example usage:
var instance = new DerivedClass();
var editor = instance.CreateEditor(); // IInterface<DerivedClass>
No, you can't do that - partly because it wouldn't make sense at compile time. Consider a slight change to your code:
BaseClass instance = new DerivedClass();
var editor = instance.CreateEditor();
What could the compiler infer the type of editor to be? It only knows about BaseClass, so it would have to return an IInterface<BaseClass>. Depending on whether or not T in IInterface<T> is covariant, that could be valid for something which actually implemented IInterface<DerivedClass> or it might not be.
You might want to make your base class generic instead:
public abstract class BaseClass<T> where T : BaseClass<T>
{
public abstract IInterface<T> CreateEditor();
}
public class DerivedClass : BaseClass<DerivedClass>
{
...
}
There are two problems with this:
It doesn't work when you go more than one level deep; if you need subclasses of DerivedClass, you'll have issues
It doesn't prevent malicious abuse of the pattern, e.g. public class NastyClass : BaseClass<DerivedClass>
... but in many cases it's quite practical.

How to require subtypes of an abstract class to implement a static instantiator?

public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.

public T GetMyClass<T>() where T : MyClass, new() { /* is this pointless? */ }

are the two methods in the class "Confused" below the same?
class MyClass
{
public override string ToString()
{
return "I am confused now";
}
}
class Confused
{
public MyClass GetMyClass()
{
return new MyClass();
}
public T GetMyClass<T>() where T : MyClass, new()
{
return System.Activator.CreateInstance<T>();
}
}
class Program
{
static void Main()
{
Confused c = new Confused();
System.Console.WriteLine(c.GetMyClass());
System.Console.WriteLine(c.GetMyClass<MyClass>());
}
}
They produce different IL, but is there any reason to write the generic version other than the 'straight up' version other than to confuse the heck out of collegues :)
If you write the generic version, you can instantiate and return derived classes:
where T : MyClass
Also, with the generic version you don't need the activation code:
return new T();
This is because you have specified:
where T : new()
The generic constraint enforcing a public parameterless constructor.
Sure there's a difference. Let's say you have a second class deriving from MyClass:
class MyClass2 : MyClass { }
Then you can do
MyClass2 myClass2 = confused.GetMyClass<MyClass2>();
You can't do that with the other function.
MyClass could be a base class (or an interface IMyClass). The generic version with the constraint says you want this function to work for any class derived from (or implementing) a common base or interface and to return the result as that derived class, not as the base.
class MyClass { }
class MySpecializedClass : MyClass { }
// etc.
There is a very big difference:
The non generic version can only return instances of type MyClass, whereas the generic version can return instances of type MyClass and all classes derived from MyClass!
No. They are not the same. The first will only ever construct a MyClass object, and the second will construct any object that is a MyClass or a descendent of MyClass, based on the type parameter.
They would give the same result ONLY if you called .GetMyClass<MyClass>(). However, I presume the extra method has been created to allow for creation of other classes? If not, then they're the same, so one's redundant (and I'd get rid of the generic version as has overhead inside the assembly).
Are they being used differently?
They are not the same. The generic allows inherited classes to be built as well like this:
class MyClass
{
public override string ToString()
{
return "I am confused now";
}
}
class InheritedClass : MyClass
{
}
class Confused
{
public MyClass GetMyClass()
{
return new MyClass();
}
public T GetMyClass<T>() where T : MyClass, new()
{
return System.Activator.CreateInstance<T>();
}
}
class Program
{
static void Main()
{
Confused c = new Confused();
System.Console.WriteLine(c.GetMyClass());
System.Console.WriteLine(c.GetMyClass<MyClass>());
System.Console.WriteLine(c.GetMyClass<InheritedClass>());
}
}
I'm not quite sure, but Generics are a runtime feature in .NET. Therefore, the non-generic method isn't equivalent to the generic one, even though it is used equivalently. As they're public, this can't be optimized away.

Why Is It That Generics Constraint Can't Be Casted to Its Derived Type?

It is quite puzzling to find out that Generics Constraint Can't Be Casted to Its Derived Type.
Let's say I have the following code:
public abstract class BaseClass
{
public int Version
{ get { return 1; } }
public string FixString { get; set; }
public BaseClass()
{
FixString = "hello";
}
public virtual int GetBaseVersion()
{
return Version;
}
}
public class DeriveClass: BaseClass
{
public new int Version
{ get { return 2; } }
}
And guess what, this method will return a compilation error:
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)baseClass;
}
I would have to cast the baseClass to object first before I can cast it to DerivedClass, i.e.,
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)((object)baseClass);
}
Seems to me pretty ugly. Why this is so?
First, you shouldn't be casting a base type variable to a derived type. It's not supposed to work, only the other way around.
Second, why it works via object, is because you remove the compile-time type checks. The compiler can check that a BaseType cannot be cast to DerivedType. But when a variable is object, the compiler leaves it assuming you know what you're doing. Even if it will compile, the code will then crash during execution.
The answer is simple: the compiler can't know that T in your FreeConversion method can be converted to DeriveClass.
As you already stated, the cheap trick is to first cast to object, then to the type you want to go. Ugly, but it works.
Apart from that, it may be that you are violating Liskov Substitution principle, nothing that will harm any animals but can drive your design towards unmaintainable code.
Third, a nice trick to let your base class expose the derived type is something like this:
public class Base<T> where T : Base<T> {
T IAmDerived;
}
public class Derived : Base<Derived> { }
First of all, in your generic method the type T could be a vale type or reference type. And the reason why it allows you to do via 'Object' is that, you're simply doing boxing-unboxing which works for any type in system.
Secondly.it will be a terrible idea to convert/cast a baseclass object into a derived class. You're violating the mechanics of OOP.
If you really want to return an object of type derived from the base class, here's one way possible - the solution is pretty much similar to what Frank has offered.
//This is how you create a function in BaseClass that returns the collection
//of DerivedTypes when called from an object of type derivedclass, no magic just Generics.
//**The BaseClass**
public class BaseClass<T>
where T : BaseClass<T>
{
public HashSet<T> GetHashSet()
{
HashSet<T> _hSet = new HashSet<T>();
//do some work
//create a HashSet<T> and return;
return _hSet;
}
}
//**The Derived Class**
public class DerivedClass : BaseClass<DerivedClass>
{
//you have the method inherited.
}

Categories

Resources