web-dev-qa-db-ja.com

ジェネリック基本クラスから継承し、制約を適用し、C#でインターフェイスを実装します

これは構文の質問です。ジェネリック基本クラスから継承し、型パラメーターの1つに制約を適用しているジェネリッククラスがあります。また、派生クラスにインターフェイスを実装する必要があります。私の人生では、正しい構文を理解できないようです。

これは私が持っているものです:

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

最初に思いついたのはこれです:

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

しかし、T2がIFooを実装するためにDerivedFooではなく、IBarとIFooの両方を実装する必要があるため、これは誤りです。

少しグーグルで試したり、コロンやセミコロンなどを使用したりしましたが、短くなりました。答えは頭が平手打ちで簡単だと確信しています。

96
Dan Rigby

ジェネリック制約を定義する前に、クラスのシグネチャ全体を含めます。

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

私の推奨事項:C#言語の構文について質問がある場合は、仕様を読んでください。それが私たちがそれを公開する理由です。セクション10.1をお読みください。

特定の質問に答えるために、クラス宣言の順序は次のとおりです。

  • 角括弧内の属性
  • 修飾子(「public」、「static」など)
  • 「部分的」
  • "クラス"
  • クラス名
  • 山かっこ内の型パラメーター宣言のコンマ区切りリスト
  • コロンは、基本型のコンマ区切りリストの後に続きます(基本クラスと実装されたインターフェース、存在する場合は基本クラスが最初に移動する必要があります)
  • 型パラメーターの制約
  • 中括弧に囲まれたクラスの本体
  • セミコロン

そのリストのすべては、「クラス」、名前、および本文を除いてオプションですが、表示される場合はすべてがその順序で表示される必要があります。

16
Eric Lippert
public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }
7
Stan R.
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になります。インターフェースを実装しませんでしたが、通常とは異なるものを必要としないはずです。

2
user875234