简体   繁体   English

方法的通用接口重载?

[英]Generic interface overloading for methods?

Is there a good, generic, way to do the following without resorting to a second method or lots of casts - I want to keep the API as light as possible and it seems ok to me OO-wise: 有没有一种好的,通用的方法可以执行以下操作,而无需求助于第二种方法或进行大量强制转换-我想使API尽可能轻便,在我看来,OO明智:

class Foo
{
  public T Bar<T>() where T: IAlpha
  {
    /* blahblahblah */
  }

  public T Bar<T>() where T: IBeta
  {
    /* blahblahblah */
  }
}

interface IAlpha
{
  string x {set;}
}

interface IBeta
{
  string y {set;}
}

thanks 谢谢

You can't overload a method by return value only (generic or not). 您不能仅通过返回值(泛型或非泛型)重载方法。 Additionally, it would be impossible to resolve calls to Bar , since an object could implement both IAlpha and IBeta , so this is not possible using overloading. 另外,将不可能解析对Bar调用,因为一个对象可以同时IAlphaIBeta ,所以使用重载是不可能的。

public class AlphaBeta : IAlpha, IBeta
{
    string x {set;}
    string y {set;}
}

// too ambiguous
AlphaBeta parkingLot = myFoo.Bar<AlphaBeta>();

The below will also not work, because the methods only differ by return type 以下方法也不起作用,因为方法仅因返回类型而异

class Gar
{
    public string Foo()
    {
        return "";
    }

    public int Foo()
    {
        return 0;
    }
}

Unfortunately, your best solution will be to use a less generic solution. 不幸的是,最好的解决方案是使用通用性较低的解决方案。 The command pattern might serve you well here. 命令模式在这里可能会为您服务。

public class Foo
{
    private readonly static Dictionary<Type, Command> factories =
        new Dictionary<Type, Command>();

    static Foo()
    {
        factories.Add(typeof(IAlpha), new AlphaCreationCommand());
        factories.Add(typeof(IBeta), new BetaCreationCommand());
    }

    public T Bar<T>()
    {
        if (factories.ContainsKey(typeof(T)))
        {
            return (T) factories[typeof(T)].Execute();
        }
        throw new TypeNotSupportedException(typeof(T));
    }
}

// use it like this
IAlpha alphaInstance = myFoo.Bar<IAlpha>();
IBeta betaInstance = myFoo.Bar<IBeta>();

Another way of implementing Bar which allows you to call it without explicitly declaring the type (in your angled brackets) is to use an out parameter. 实现Bar而无需显式声明类型(在尖括号中)的方式调用Bar的另一种方法是使用out参数。 I'd avoid it, however, since out parameters in 100% managed usually stink of bad design. 但是,我会避免使用它,因为100%管理的参数通常会导致不良设计。

public void Bar<T>(out T returnValue)
{
    if (factories.ContainsKey(typeof(T)))
    {
        returnValue = (T) factories[typeof(T)].Execute();
        return;
    }
    throw new TypeNotSupportedException(typeof(T));
}

// call it like this
// T is inferred from the parameter type
IAlpha alphaInstance;
IBeta betaInstance;
myFoo.Bar(out alphaInstance);
myFoo.Bar(out betaInstance);

I excluded Command , AlphaCreationCommand , BetaCreationCommand , and TypeNotSupportedException . 我排除了CommandAlphaCreationCommandBetaCreationCommandTypeNotSupportedException Their implementation should be fairly self explanatory. 它们的实现应该是相当自我解释的。

Alternately, you can use Func instead of Commands, but this forces you to implement all of your instantiation code in Foo which can get out of hand as your code base grows. 或者,您可以使用Func代替Commands,但是这迫使您在Foo实现所有实例化代码,随着代码库的增加,这些实例化代码可能会失控。

How about this? 这个怎么样?

class Foo
{
  public void Bar<T>(Action<T> @return) where T: IAlpha
  {
    @return(new AlphaImpl());
  }

  public void Bar<T>(Action<T> @return) where T: IBeta
  {
    @return(new BetaImpl());
  }
}

interface IAlpha
{
  string x {set;}
}

interface IBeta
{
  string y {set;}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM