从通用基类继承,应用约束,并在C#中实现接口

Dan*_*gby 102 c# generics inheritance interface constraints

这是一个语法问题.我有一个泛型类,它继承自泛型基类,并将约束应用于其中一个类型参数.我还希望派生类实现一个接口.对于我的生活,我似乎无法弄清楚正确的语法.

这就是我所拥有的:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar { ... }
Run Code Online (Sandbox Code Playgroud)

首先想到的是:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar, IFoo { ... }
Run Code Online (Sandbox Code Playgroud)

但这是不正确的,因为这导致T2需要实现IBar和IFoo,而不是DerivedFoo来实现IFoo.

我尝试了一些谷歌搜索,使用冒号,分号等,但我已经调整了.我确定答案很简单.

Ada*_*son 154

在定义泛型约束之前,请包括类的完整签名.

class DerivedFoo<T1, T2> : ParentFoo<T1, T2>, IFoo where T2 : IBar
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 对于其他人,我已将其内化为,一个类只获得一个where子句,并且它最后用于任何和所有泛型类型约束. (4认同)

Eri*_*ert 16

我的建议:当你对C#语言的语法有疑问时,请阅读规范; 这就是我们发布它的原因.您需要阅读第10.1节.

要回答您的具体问题,类声明中的事物顺序是:

  • 方括号中的属性
  • 修饰符("public","static"等)
  • "局部"
  • "类"
  • 班级名称
  • 尖括号内的逗号分隔的类型参数声明列表
  • 冒号后面跟着逗号分隔的基类型列表(基类和已实现的接口,如果有基类,必须首先进行基类)
  • 类型参数约束
  • 班上的身体,被牙套包围
  • 分号

除了"class",名称和正文之外,该列表上的所有内容都是可选的,但如果出现,则所有内容都必须按顺序显示.

  • 埃里克,虽然我非常尊重你作为一名专业人士,并感谢你的反馈,但我不禁会因为一个磨砺的答案而感到沮丧.您批评我选择在编程问答网站上提出问题,而不是通过MSDN中链接的高度技术性的503页Word文档进行查找,下载和搜索.那太粗糙了.这是我对时间的最有效利用,并且具有额外的好处,可以在以后帮助其他人.有兴趣的人可以找到C#Lang Spec的链接:http://msdn.microsoft.com/en-us/vcsharp/aa336809.aspx (83认同)
  • 没有任何批评意图.纯文本传播中普遍存在偏见,这使得简单的事实陈述听起来粗鲁无礼; 在提供一系列有用的事实时,我试着仔细阅读,并建议您也这样做.我支持我的建议; 如果您对语法有疑问,那么规范肯定会回答它们,并从一个有用的目录开始,用于查找特定语法的定义. (15认同)
  • Dan,发现C#规范就像在Google中输入"C#Spec"并点击"我很幸运"按钮一样简单.如果您是专业的C#开发人员,您应该已经在您的计算机上拥有PDF格式的C#规范.另外,我也不是要批评你.我之前不习惯阅读规范,但我已经开始阅读它了,感谢Jon,Eric和Pavel总是引用C#规范来解决任何问题.我发现C#规范虽然有时难以阅读,但却是学习语言的好方法. (2认同)
  • C++*要求*类声明以分号结尾.许多C#开发人员来自C++背景; 有时他们的手指将分号放入,而不会让他们的大脑介入.:-) C#中有许多构造,它们采用可选的半开头,而C++需要一个.这只是一个微妙的便利.我想它也可以让你在类型声明结束时巧妙地调用vs一个方法体声明. (2认同)

Sta*_* R. 8

public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }
Run Code Online (Sandbox Code Playgroud)