I have an interface that for example's sake looks like this:
interface IFoo<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable
{
TEnum MyEnum { get; set; }
}
I then have an abstract base class that looks like this:
abstract class FooBase<TEnum> : IFoo<TEnum> where TEnum : struct, IConvertible, IFormattable, IComparable
{
public TEnum MyEnum { get; set; }
}
I then inherit from the base class like so:
class MyFoo : FooBase<MyFoo.MyFooEnum>
{
public enum MyFooEnum
{
Foo1,
Foo2,
}
}
How can I instantiate a MyFoo
from a generic method with type parameter FooBase
?
I'm pretty much looking for something like this:
static class FooMethods
{
public static TFooClass GetFoo<TFooClass>() where TFooClass : FooBase, new()
{
TFooClass fooclass = new TFooClass();
return fooclass;
}
}
The problem I have is that it wants type parameters for FooBase
, but in reality I don't really care what the parameters are since my MyFoo
has those type parameters already.
Only generic classes can implement generic interfaces. Normal classes can't implement generic interfaces.
You can declare variant generic interfaces by using the in and out keywords for generic type parameters. ref , in , and out parameters in C# cannot be variant. Value types also do not support variance. You can declare a generic type parameter covariant by using the out keyword.
A generic interface is primarily a normal interface like any other. It can be used to declare a variable but assigned the appropriate class. It can be returned from a method. It can be passed as argument. You pass a generic interface primarily the same way you would an interface.
You can inherit your generic class from a common base:
abstract class FooBase {
}
abstract class FooBase<TEnum> : FooBase, IFoo<TEnum>
where TEnum : struct, IConvertible, IFormattable, IComparable {
public TEnum MyEnum { get; set; }
}
public static TFooClass GetFoo<TFooClass>()
where TFooClass : FooBase, new() {
TFooClass fooclass = new TFooClass();
return fooclass;
}
But you won't be able to access the MyEnum
property with a generic constraint of FooBase
. (And how could you, without having specified the type?)
That, or you need to add another type parameter to GetFoo
:
abstract class FooBase<TEnum> : IFoo<TEnum>
where TEnum : struct, IConvertible, IFormattable, IComparable {
public TEnum MyEnum { get; set; }
}
public static TFooClass GetFoo<TFooClass, TEnum>()
where TFooClass : FooBase<TEnum>, new()
where TEnum : struct, IConvertible, IFormattable, IComparable {
TFooClass fooclass = new TFooClass();
return fooclass;
}
UPDATE: Another thing I could point out is that if you find that you need to call this GetFoo
method a lot, then if you put it in an instance class instead of a static class, you can push one or both of the type arguments up into the class instead of always specifying it in the method. This can make some code a little less verbose, but really only if you call this method a lot. Ex:
public sealed FooFactory<TEnum>
where TEnum : struct, IConvertible, IFormattable, IComparable {
public static TFooClass GetFoo<TFooClass>()
where TFooClass : FooBase<TEnum>, new() {
TFooClass fooclass = new TFooClass();
return fooclass;
}
}
...
var factory = new FooFactory<SomeEnum>();
var foo1 = factory.GetFoo<SomeFooClass1>();
var foo2 = factory.GetFoo<SomeFooClass2>();
// or the other way:
var factory = new FooFactory<SomeFooClass>();
var foo1 = factory.GetFoo<SomeEnum1>();
var foo2 = factory.GetFoo<SomeEnum2>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With