具有接口类型约束的C#泛型方法

Tim*_*non 3 c# generics interface

我们假设我有:

  • 一般方法 Get<T>
  • 一些接口IEntity,IValue
  • 一些分别实现这些接口的类:Entity- > IEntity,Value- > IValue等.

=>该Get<T>方法是否有办法仅允许接口作为泛型类型?

Get<IEntity>(42); //Allowed
Get<Entity>(42);  //Compiler error
Run Code Online (Sandbox Code Playgroud)

我目前的解决方案如下:

  • Get<T>具有Type约束的通用方法where T: IPersistable(以防止大多数类型作为参数传递)
  • 接口实现 IPersistable

该函数主动检查类型:

public T Get<T>(long id) where T : IPersistable
{
   if (typeof (T) == typeof (IEntity))
      return (T) EntityDao.Get(id);
   if (typeof (T) == typeof (IValue))
      return (T) ValueDao.Get(id);

   //...

   throw new TechnicalException("Type not supported");
}
Run Code Online (Sandbox Code Playgroud)

=>问题是:

  1. 它不干净......我可以忍受它,因为只有很少的类型可以检查
  2. 签名与函数的确无关.它允许IPersistablein,但不是真的< - 真的让我烦恼:(

编辑:我正在考虑这样的限制,以避免我班上的人口过剩.

我在那个类中有类似8或9个泛型方法的东西,它们都以这种方式工作.直观的做法是@DanielHilgarth建议每种类型只有1种方法.目前可以使用4种或5种类型调用这些方法.但是,这仍然意味着该课程中有32-40种方法.

如果可能的话,我想避免这种情况.

Edit2:防止"真实"类被调用的需要来自协方差/逆变问题.EntityDao和ValueDao Get<T>方法返回IEntityIValue对象.当我在一个GetAll<T>方法中调用一个集合时,当我查询单个对象失败时,什么工作正常,因为我无法在一个方法IEnumerable<IValue>中强制转换IEnumerable<Value>.

我刚刚注意到@JonSkeets关于列表的回答.这可能是一个解决方法......

Dan*_*rth 5

您应该只创建专用方法.示例代码if显示您当前的方法不做一件事.它做多个.

请跟:

GetEntity(42);
GetValue(13);

public IEntity GetEntity(long id)
{
    return EntityDao.Get(id);
}

public IValue GetValue(long id)
{
    return ValueDao.Get(id);
}
Run Code Online (Sandbox Code Playgroud)

所有图层都更清晰:

  1. GetEntityGet<IEntity>
  2. 你清楚地传达了可能的信息.您没有任何运行时异常.
  3. 您的get方法不需要任何类型切换.

如果这会导致您的服务上有太多类似的方法,那么就应该打破新的类,例如一个for Entity和一个for Value.然后,您可以提供返回新类的服务属性.这与我在实现查询对象时所做的相同.它可能看起来像这样:service.Values.Get(13)service.Entities.Get(42)