Interface Base class instantiation via generic method

人盡茶涼 提交于 2020-01-03 11:13:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!