问题
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.
回答1:
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>();
回答2:
You can do next:
abstract class FooBase
{
}
abstract class FooBase<TEnum> : FooBase, IFoo<TEnum> where TEnum : struct, IConvertible, IFormattable, IComparable
{
public TEnum MyEnum { get; set; }
}
static class FooMethods
{
public static TFooClass GetFoo<TFooClass>() where TFooClass : FooBase, new()
{
TFooClass fooclass = new TFooClass();
return fooclass;
}
}
来源:https://stackoverflow.com/questions/33285222/interface-base-class-instantiation-via-generic-method