方法的通用接口重载?

3 c# generics overloading interface

有没有一种好的,通用的方法来执行以下操作而无需使用第二种方法或大量的强制转换 - 我希望尽可能保持API的亮度,对我来说似乎没问题:

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;}
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Mic*_*ows 7

您不能仅通过返回值重载方法(通用或不通用).此外,这将是不可能解决的呼吁Bar,因为一个对象可以同时实现IAlphaIBeta,所以这个使用重载是不可能的.

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

// too ambiguous
AlphaBeta parkingLot = myFoo.Bar<AlphaBeta>();
Run Code Online (Sandbox Code Playgroud)

以下也不起作用,因为方法仅因返回类型而不同

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

    public int Foo()
    {
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,您最好的解决方案是使用不太通用的解决方案.命令模式可能在这里很好用.

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>();
Run Code Online (Sandbox Code Playgroud)

另一种实现Bar的方法是允许你在没有明确声明类型(在斜角括号中)的情况下调用它,就是使用out参数.但是,我会避免这种情况,因为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);
Run Code Online (Sandbox Code Playgroud)

我排除了Command,AlphaCreationCommandBetaCreationCommand,和TypeNotSupportedException.它们的实施应该是相当自我解释的.

或者,您可以使用Func而不是Commands,但这会强制您实现所有实例化代码,Foo随着代码库的增长,这些代码可能会失控.