方法的通用接口重载?

3

是否有一种好的通用方法能够完成以下操作,而不需要使用第二个方法或大量类型转换——我希望尽可能地保持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;}
}

谢谢

2个回答

7

你无法仅通过返回值(无论是通用的还是非通用的)来重载一个方法。此外,由于一个对象可以同时实现 IAlphaIBeta,因此无法解析对 Bar 的调用,因此不能使用重载。

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

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

下面的方法也无法工作,因为这些方法只有返回类型不同。
class Gar
{
    public string Foo()
    {
        return "";
    }

    public int Foo()
    {
        return 0;
    }
}

很遗憾,您最好的解决方案是使用一个不那么通用的解决方案。命令模式可能在这里为您服务。

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>();

另一种实现Bar的方式是使用输出参数,这样可以在不明确声明类型(在尖括号中)的情况下调用它。然而,我建议避免使用它,因为在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);

我排除了Command, AlphaCreationCommand, BetaCreationCommand, 和 TypeNotSupportedException。它们的实现应该相当容易理解。

或者,你可以使用Func而不是Commands,但这会强制你在Foo中实现所有的实例化代码,随着代码库的增长,这可能会变得不可控。


它不会为实现了两者的类型编译。但对于所有其他类型,它将会编译(您的措辞暗示它不会编译)。 - Colin Burnett
我不知道仅通过返回类型进行方法重载何时编译。如果您能提供一个示例,我可以编辑我的答案以进行更正。 - Michael Meadows

1

这个怎么样?

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;}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接