C#:在泛型类中添加条件泛型方法(不同的通用限制)

时间:2009-06-01 21:36:47

标签: c# linq

我正在尝试为泛型类中的方法添加另一个限制。这可能吗?

伪代码:

public class MyBaseClass<T> where T: class
{
    public IQueryable<T> ShowThisMethod where T: class, IMyInterface
    {
         // stuff.
    }
}

public class MyBaseClass<T> where T: class { public IQueryable<T> ShowThisMethod where T: class, IMyInterface { // stuff. } }

ShowThisMethod仅在T为IMyInterface时才可用。此外,IMyInterface应该返回信息(关于T),以便我可以访问方法内的IMyInterface中定义的属性。

帮助:)

顺便说一下,这个编译(并且似乎“差不多”):

public class MyBaseClass<T> where T: class
{
    public IQueryable<T> ShowThisMethod<T>() where T: class, IMyInterface
    {
        String X = T.MyInterfaceStringProperty;
    }
}

有关我的目标的更多信息

我正在使用通用基类来访问公共属性(LINQ对象 Dinner 上的DateTime“Time”属性,该属性也在 Lunch 上)。

两个对象都实现了 ITimeable ,它暴露了DateTime属性。

在我的基类中,我想要一个方法Select(),它适用于IQueryable&amp; ltT&gt;并可以根据Time属性自动过滤。因为我正在使用泛型T,所以时间属性对于基类是不可见的,除非我告诉它T正在实现 ITimeable

我确实希望相同的基类也适用于其他非ITimeable对象,这就是我需要Select方法的接口限制的原因,我还需要它来使用泛型访问Time属性。

希望清除目标:)

P.S。我主要担心的是智能感知等方法的可见性。。我只想保持我的基类工作,同时能够通过泛型访问接口指定的属性。

5 个答案:

答案 0 :(得分:3)

这取决于你想要什么。

由于类被编译一次,并且泛型的魔法也依赖于运行时,因此在某些情况下无法创建具有某些方法的类,而在其他情况下则无法创建其他方法。这些方法都存在,或者它们不存在。

所以基本上,没有办法声明MyBaseClass以便发生以下情况:

MyBaseClass<Int32>  bc;
bc. <-- intellisense does not show ShowThisMethod here

MyBaseClass<SomeTypeImplementingIMyInterface> bc2;
bc2. <-- intellisense DOES show ShowThisMethod here

......这本身就是......

你可以“欺骗”编译器和智能感知为你提供你所要求的东西,但要知道这给你带来了可能需要解决的其他限制和挑战。

基本上,通过向与MyBaseClass一起声明的静态类添加扩展方法,可以使智能感知和编译器的行为就像当T具有某些特定规则时,该方法仅适用于MyBaseClass,就像您要求的那样

但是,由于所讨论的方法是一个静态方法,在MyBaseClass之外定义,你可以访问的MyBaseClass内部有多少限制,而且你无法访问MyBaseClass中的方法,所以它依赖于你想要完成什么,以及你是否可以忍受这些限制。

无论如何,这是扩展方法。请注意,您同时从MyBaseClass中完全删除它:

public static class MyBaseClassExtensions
{
    public static IQueryable<T> ShowThisMethod<T>(this MyBaseClass<T> mbc)
        where T: class, IMyInterface
    {
        ...
    }
}

答案 1 :(得分:2)

另请注意,ShowThisMethod在ShowThisMethod的上下文中重新定义 T.它与班级定义的T不同。

指定一个不同的Type参数,其中新的类继承自类定义的类型参数将是最好的方法,但最终需要调用者必须指定两次泛型类型。

答案 2 :(得分:1)

不,这是不可能的。约束在声明时定义。在这种情况下,方法不是通用的,类是(它是泛型类的非泛型方法)。因此约束只能在类本身上声明。

答案 3 :(得分:1)

这会做你想要的吗?任何人都可以看到该方法,但不一定可用......

public class MyBaseClass<T> where T: class
{
    public IQueryable<R> ShowThisMethod() where R: T, IMyInterface
    {
         Debug.Assert(typeof(R) == typeof(T));
         // stuff.
    }
}

答案 4 :(得分:1)

您可以定义另一个继承MyBaseClass的类并重新定义约束:

public MyOtherClass<T> : MyBaseClass<T> where T : class, IMyInterface
{
    public IQueryable<T> ShowThisMethod()
    {
        // stuff.
    }
}