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


117

这是一个语法问题。我有一个泛型类,它是从泛型基类继承的,并且将约束应用于类型参数之一。我还希望派生类实现一个接口。对于我的一生,我似乎无法找出正确的语法。

这就是我所拥有的:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar { ... }

我想到的第一件事是:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar, IFoo { ... }

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

我尝试了一些谷歌搜索,冒号,分号等的使用,但是结果却很短。我确定答案很简单。


当我看了一次,我听不懂@Adam的回答,但是2分钟后我就明白了,谢谢你的回答。派生类具有多个实现可能就是这一点。无论如何,我想向他人展示它的符号。“ class DerivedClass <Type>:ParentClass,其中Type:IType”。最后实现的类和where子句之间不应存在任何内容。
nurisezgin

Answers:


173

在定义通用约束之前,您应包括类的整个签名。

class DerivedFoo<T1, T2> : ParentFoo<T1, T2>, IFoo where T2 : IBar
{
    ...
}

5
对于其他人,我将其内部化为,一个类仅获得一个where子句,并且在所有通用类型约束的最后。

@Visser它允许有多个where子句,类测试<T1,T2>其中,T1:接口1,其中T 2:接口2
bwing

@Visser是的,bwing所说的话,每个where子句也可以有多个约束…因此原始文章中的语法是正确的,只是意味着操作员想要的东西有所不同。where T2 : IBar, IFoo 只是意味着T2必须实现两个接口而不是DerivedFoo<T1,T2> 实现IFoo
v01pe

18

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

为了回答您的特定问题,类声明中的事物顺序为:

  • 属性,在方括号中
  • 修饰符(“公共”,“静态”等)
  • “部分”
  • “类”
  • 班级名称
  • 用尖括号括起来的类型参数声明的逗号分隔列表
  • 冒号后跟一个逗号分隔的基本类型列表(基本类和已实现的接口,如果有一个,则基本类必须排在最前面)
  • 类型参数约束
  • 类的主体,被大括号包围
  • 分号

除“类”,名称和正文外,列表上的所有内容都是可选的,但如果出现,则所有内容必须按该顺序显示。


95
埃里克(Eric),尽管我非常尊敬您的专业知识并感谢您的反馈,但我还是不禁为这个严厉的回答而感到沮丧。您批评我选择在编程问答网站上提问,而不是查找,下载和搜索隐藏在MSDN链接中的,技术含量高的503页Word文档。那很粗糙。这是我时间​​上最有效的利用方式,它具有额外的好处,可以在以后帮助其他人。感兴趣的C#语言规范的链接是:msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
Dan Rigby,2010年

17
没有批评的意图。纯文本交流中普遍存在偏见,使得简单的事实陈述听起来很粗鲁和刺耳。当出现一系列有用的事实时,我会尽量慈善地阅读,并建议您也这样做。我坚持我的建议;如果您对语法有疑问,那么本规范将明确解答这些问题,并从一个有用的目录开始,以查找特定语法的定义。
埃里克·利珀特

3
Dan,找到C#规范就像在Google中输入“ C#规范”并点击“我很幸运”按钮一样简单。并且,如果您是专业的C#开发人员,则您的计算机上应该已经有PDF格式的C#规范。另外,我也不是要批评你。我以前不习惯阅读规范,但是由于Jon,Eric和Pavel总是引用C#规范来解答任何问题,因此我开始阅读它。我发现C#规范尽管有时可能很难阅读,但却是了解该语言的好方法。
SolutionYogi 2010年

@埃里克·利珀特:足够公平。谢谢您的回复。作为一个建设性的建议,如果Microsoft将规范的内容直接作为单独的下载文件存在,那么将其直接集成到MSDN中将很有帮助。Visual Studio .Net MSDN版本具有规范的集成版本,但没有更高版本。我已经考虑过购买Anders Hejlberg的书,但是对于即将推出的.Net 4.0,我还是不愿意。amazon.com/C-Programming-Language-3rd/dp/0321562992谢谢。
丹·里格比

2
C ++ 要求类声明以分号结尾。许多C#开发人员都来自C ++背景。有时,他们的手指会把分号放进去,而他们的大脑不会参与进来。:-) C#中有许多结构,它们带有一个可选的半符号,其中C ++需要一个。这几乎只是一个微妙的便利。我想它还可以让您在类型声明结束时巧妙地呼出,而不是说方法主体声明。
埃里克·利珀特

8
public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }

2
public class KeyAndValue<T>
{
    public string Key { get; set; }
    public virtual T Value { get; set; }
}

public class KeyAndValue : KeyAndValue<string>
{
    public override string Value { get; set; }
}

这是现有答案的扩展。string如果您不提供类型,则默认为默认值。我没有实现接口,但不需要任何与平常不同的东西。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.