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

具有接口类型约束的C#泛型方法,c#,generics,interface,C#,Generics,Interface,让我们假设我有: 通用方法Get 一些接口IEntity,IValue 分别实现这些接口的几个类,例如:Entity->ienty,Value->IValue等 =>有没有办法让Get方法只允许将接口作为泛型类型? Get<IEntity>(42); //Allowed Get<Entity>(42); //Compiler error =>问题是: 它不干净。。。我可以接受这一点,因为只有很少的类型可以检查 签名与函数的实际功能不匹配。它允许在中使用IPersi

让我们假设我有:

  • 通用方法
    Get
  • 一些接口
    IEntity
    IValue
  • 分别实现这些接口的几个类,例如:
    Entity
    ->
    ienty
    Value
    ->
    IValue
=>有没有办法让
Get
方法只允许将接口作为泛型类型?

Get<IEntity>(42); //Allowed
Get<Entity>(42);  //Compiler error
=>问题是:

  • 它不干净。。。我可以接受这一点,因为只有很少的类型可以检查

  • 签名与函数的实际功能不匹配。它允许在中使用
    IPersistable
    ,但实际上不是,您应该创建专用的方法。带有
    if
    的示例代码显示当前方法没有做一件事。它有多重功能

    只需使用:

    GetEntity(42);
    GetValue(13);
    
    public IEntity GetEntity(long id)
    {
        return EntityDao.Get(id);
    }
    
    public IValue GetValue(long id)
    {
        return ValueDao.Get(id);
    }
    
    这在所有图层上都非常干净:

  • GetEntity
    vs.
    Get
  • 你清楚地表达了一切可能。您没有任何运行时异常
  • get方法不需要任何类型切换
  • 如果这将导致在您的服务上使用太多类似的方法,则是时候划分新的类了,例如一个类用于
    实体
    ,另一个类用于

    然后,您可以提供返回新类的服务属性。这与我在实施时所做的相同。然后它可能看起来像这样:
    service.Values.Get(13)
    service.Entities.Get(42)

    这可能是另一种选择:

    abstract class Persistable<T>
    {
        protected static Func<long, T> mapFunction;
        public static T Get(long id)
        {
            return mapFunction(id);
        }
    }
    
    class Entity : Persistable<Entity>
    {
        public static Entity()
        {
            Persistable<Entity>.mapFunction = input => EntityDao.Get(input);
        }
    }
    class Value : Persistable<Value>
    {
        public static Value()
        {
            Persistable<Value>.mapFunction = input => ValueDao.Get(input);
        }
    }
    

    你能解释一下,为什么你需要这样的约束?当然,我刚刚编辑了这个问题。这是一个解释,为什么你想让泛型方法代替工厂方法的数量。如果你能解释一下,为什么这个方法应该只限于接口类型,那会很有帮助。我可以,但我担心我的类中的方法“过多”。我有8个或9个泛型方法,它们在那个类中都以类似的方式工作。如果我分解了我的通用方法,我会得到大约40个方法。如果可能的话,我想避免这种情况。@TimBourguignon:那样的话,你应该开发一些新的类。这确实是一种可能性。。。这是我一直试图避免的,因为该服务中的单个入口点确实很方便(所有提到的方法都是getter,所以在某种程度上,将它们都分组在一起是有意义的)…您可以提供返回新类的服务属性。这与我在实施时所做的相同。它可以是这样的:
    service.Values.Get(13)
    service.Entities.Get(42)
    。我必须仔细考虑一下,但这是个好主意,它看起来确实很性感:D
    abstract class Persistable<T>
    {
        protected static Func<long, T> mapFunction;
        public static T Get(long id)
        {
            return mapFunction(id);
        }
    }
    
    class Entity : Persistable<Entity>
    {
        public static Entity()
        {
            Persistable<Entity>.mapFunction = input => EntityDao.Get(input);
        }
    }
    class Value : Persistable<Value>
    {
        public static Value()
        {
            Persistable<Value>.mapFunction = input => ValueDao.Get(input);
        }
    }
    
    public T Get<T>(long id) // maybe you restrict the T to something
    {
        Persistable<T>.Get(id);
    }