方法的通用接口重载? [英] Generic interface overloading for methods?

查看:117
本文介绍了方法的通用接口重载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种很好的,通用的方式来执行以下操作,而不诉诸第二种方法或大量的强制转换 - 我希望保持API尽可能轻,而且对我来说看起来确实OO明智:

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

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

接口IAlpha
{
字符串x {集合;}
}

接口IBeta
{
string y {set;}
}

谢谢

解决方案

你不能仅仅通过返回值来重载一个方法(通用或不)。另外,由于一个对象可以同时实现 IAlpha 和<$ c $,所以不可能解析对 Bar 的调用

  public class AlphaBeta:IAlpha,IBeta  ,所以这是不可能的使用重载。 
{
string x {set;}
string y {set;}
}

//模糊
AlphaBeta parkingLot = myFoo &标尺示LT;的Alpha-Beta>();

以下内容也无法使用,因为这些方法仅仅因返回类型而异

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

public int Foo()
{
return 0;






$ b

不幸的是,你最好的解决方案是使用更少的通用解决方案

  public class Foo 
{
private readonly static Dictionary<类型,命令>工厂=
新词典< Type,Command>();

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

$ b $ public T Bar< T>()
{
if(factories.ContainsKey(typeof(T)))
{
返回(T)工厂[typeof(T)] .execute();
}
抛出新的TypeNotSupportedException(typeof(T));



//像这样使用
IAlpha alphaInstance = myFoo.Bar< IAlpha>();
IBeta betaInstance = myFoo.Bar< IBeta>();

另一种实现Bar的方法,可以在不明确声明类型的情况下调用它(在角括号中)是使用out参数。然而,我会避免它,因为100%管理的out参数通常会导致设计不好。

  public void Bar< T> ;(out T returnValue)
{
if(factories.ContainsKey(typeof(T)))
{
returnValue =(T)factories [typeof(T)]。 ();
return;
}
抛出新的TypeNotSupportedException(typeof(T));
}

//这样调用
// T从参数类型
IAlpha alphaInstance推断出来;
IBeta betaInstance;
myFoo.Bar(out alphaInstance);
myFoo.Bar(out betaInstance);

我排除了命令 AlphaCreationCommand BetaCreationCommand TypeNotSupportedException 。它们的实现应该是相当自我解释的。

或者,您可以使用Func而不是命令,但是这迫使您在 Foo 随着代码库的增长,它可能会失控。


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:

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.

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. I'd avoid it, however, since out parameters in 100% managed usually stink of bad design.

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. 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.

这篇关于方法的通用接口重载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆