我正在尝试为泛型类中的方法添加另一个限制。这可能吗?
伪代码:
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。我主要担心的是智能感知等方法的可见性。。我只想保持我的基类工作,同时能够通过泛型访问接口指定的属性。
答案 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.
}
}