Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C:在泛型类中添加条件泛型方法(不同的泛型限制)_C#_Linq - Fatal编程技术网

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

C# C:在泛型类中添加条件泛型方法(不同的泛型限制),c#,linq,C#,Linq,我试图在泛型类中对方法添加另一个限制。这可能吗 伪代码: 显示此方法仅在T为IMY接口时可用。此外,IMyInterface还应该返回关于T的信息,以便我可以访问方法内部IMyInterface中定义的属性 帮助: 顺便说一句,这是正确的: 有关我的目标的更多信息: 我正在使用一个泛型基类访问LINQ对象晚餐上的一个公共属性DateTime属性,这也是午餐时间 这两个对象都实现了ITimeable,它公开了DateTime属性 在我的基类中,我希望有一个方法Select,它可以在IQuerya

我试图在泛型类中对方法添加另一个限制。这可能吗

伪代码:

显示此方法仅在T为IMY接口时可用。此外,IMyInterface还应该返回关于T的信息,以便我可以访问方法内部IMyInterface中定义的属性

帮助:

顺便说一句,这是正确的:

有关我的目标的更多信息:

我正在使用一个泛型基类访问LINQ对象晚餐上的一个公共属性DateTime属性,这也是午餐时间

这两个对象都实现了ITimeable,它公开了DateTime属性

在我的基类中,我希望有一个方法Select,它可以在IQueryable<T>上工作,并且可以根据Time属性自动过滤。因为我使用的是泛型T,所以time属性对基类不可见,除非我告诉它T正在实现ITimeable

我确实希望相同的基类也适用于其他非ITimeable对象,这就是为什么我需要Select方法上的接口限制,并且我还需要它,以便使用泛型访问Time属性

希望明确目标:


另外,我主要关心的是该方法在智能感知等方面的可见性。。我只想让基类继续工作,同时能够通过其中的泛型访问接口指定的属性。

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

这取决于您想要什么

由于该类只编译一次,并且泛型的魔力也依赖于运行时,因此无法生成在某些情况下具有某些方法,而在其他情况下具有其他方法的类。方法要么存在,要么不存在

因此,基本上,没有办法声明MyBaseClass,从而发生以下情况:

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

MyBaseClass<SomeTypeImplementingIMyInterface> bc2;
bc2. <-- intellisense DOES show ShowThisMethod here
。。。那就是。。。它本身

您可以欺骗编译器和intellisense,使其满足您的要求,但要知道,这会给您带来其他可能需要解决的限制和挑战

基本上,通过向MyBaseClass旁边声明的静态类添加扩展方法,您可以实现intellisense,编译器的行为就好像只有当T具有某些特定规则时,才为MyBaseClass提供该方法,正如您所要求的那样

然而,由于所讨论的方法是在MyBaseClass之外定义的静态方法,因此您可以访问MyBaseClass内部的数量是有限制的,并且您不能访问MyBaseClass内部的方法,因此这取决于您想要完成什么,以及您是否能够接受这些限制

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

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

这能满足你的需要吗?该方法将对任何人可见,但不一定可用

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

还要注意,ShowThisMethod在ShowThisMethod的上下文中重新定义了T。它与类定义的T不同


指定新类型参数继承自类定义的类型参数的不同类型参数是最好的方法,尽管这最终要求调用方必须指定两次泛型类型。

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

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

第二段代码没有为我编译,我收到一条错误消息,指出类型参数“t”与外部类型“…MyBaseClass”中的类型参数具有相同的名称。我也收到一条警告,是的,但为我编译。这与重新定义约束不同。例如,基本上可以使用类似MyBaseClass.ShowThisMethod的方法。我怀疑这是你想要的。啊,警告,错误,它们都是一样的,不是吗?好吧,太晚了,该睡觉了,我想:是啊,那不是我想要的。。。我不想使用类实例,只想在T中添加IMyInterface的要求来显示此方法。谢谢你这么说,但请保留对你使用扩展方法的赞扬。我很确定你一开始没有看到一些陷阱,至少我有一种唠叨的感觉…:我会在5分钟内知道,已经在调整我的代码:我会让你知道的。但我认为它会起作用的!啊哈。一个警告。这是存储库的一部分,返回IRepository。现在我需要获得IRepository,以便有条件地查看方法:
public class MyBaseClass<T> where T: class
{
    public IQueryable<R> ShowThisMethod() where R: T, IMyInterface
    {
         Debug.Assert(typeof(R) == typeof(T));
         // stuff.
    }
}
public MyOtherClass<T> : MyBaseClass<T> where T : class, IMyInterface
{
    public IQueryable<T> ShowThisMethod()
    {
        // stuff.
    }
}