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


117

これは構文の質問です。ジェネリック基本クラスから継承し、型パラメーターの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の両方を実装する必要があるため、正しくありません。

私はグーグル、コロン、セミコロンの使用などを少し試しましたが、短くなりました。答えはきっと簡単です。


@Adamの答えを1度見たところ理解できませんでしたが、2分後には答えがわかりました。派生クラスには複数の実装があり、これがポイントです。とにかく、その表記を他の人に見せたいです。"クラスDerivedClass <Type>:ParentClass where Type:IType"。最後に実装されたクラスとwhere句の間に何もないはずです。
nurisezgin

回答:


173

一般的な制約を定義する前に、クラスの署名全体を含めます。

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

5
他の人には、これを内部化しました。クラスは1つのwhere句しか取得せず、すべてのジェネリック型制約の最後に配置されます。
アンディV

@Visser複数のwhere句を使用できます。クラスTest <T1、T2> where T1:Interface1 where T2:Interface2
bwing

@Visserええ、bwingの言ったこと、各where句には複数の制約がある可能性があります...したがって、元の投稿の構文は正しいので、opが望んだ別の意味になります。where T2 : IBar, IFoo ちょうど手段T2の代わりに、両方のインタフェースを実装しなければならないDerivedFoo<T1,T2> 実装IFoo
v01pe

18

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

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

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

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


95
エリック、私はあなたをプロとして尊敬し、あなたのフィードバックに感謝しますが、私は研磨的な答えとして出くわすものに不満を感じざるを得ません。MSDNのリンクから埋め込まれた非常に技術的な503ページのWord文書の検索、ダウンロード、検索について、プログラミングQ&Aサイトで質問することを選択したことについて私を批判しています。それはかなりラフです。これは私の時間の最も効率的な使用であり、後で他の人を助けることができるという追加の利点があります。興味のある方のためのC#Lang Specへのリンクは次のとおりです。msdn.microsoft.com
Dan Rigby

17
批判は意図されていなかった。純粋なテキストコミュニケーションには、偏見が広がっており、事実の簡単な説明が無茶苦茶で研ぎ澄まされています。私は有益な事実のリストが提示されたときに慈善的に読むようにしており、そうすることもお勧めします。私は私の推薦を支持します。構文について質問がある場合、仕様は明確に回答し、特定の構文の定義を見つけるのに役立つ目次から始まります。
Eric Lippert

3
ダン、C#仕様を見つけるのは、Googleで「C#仕様」と入力して「私はラッキーです」ボタンを押すのと同じくらい簡単です。また、プロのC#開発者であれば、マシンにPDF形式のC#仕様がすでにあるはずです。また、私はあなたを批判するつもりもありません。以前は仕様を読むのに慣れていませんでしたが、質問には常にC#仕様を引用しているJon、Eric、Pavelのおかげで読み始めました。C#の仕様は、時々読むのは難しいかもしれませんが、言語について学ぶのに最適な方法であることがわかりました。
SolutionYogi

@Eric Lippert:十分に公正です。お返事ありがとうございます。建設的な提案として、Microsoftが仕様のコンテンツを別個のダウンロードとして存在させることに加えて、MSDNに直接統合することは有用です。Visual Studio .Net MSDNバージョンには、仕様の統合バージョンがありますが、それ以降のバージョンはありません。私はAnders Hejlbergの本を購入することを考えましたが、.Net 4.0が近づいているので、私はまだ気が進まないのです。amazon.com/C-Programming-Language-3rd/dp/0321562992ありがとう。
Dan Rigby、2010年

2
C ++ では、クラス宣言がセミコロンで終了する必要があります。多くのC#開発者はC ++の出身です。時々、彼らの指は彼らの脳が関与することなくセミコロンを入れます。:-) C#には、C ++が必要とするオプションのセミを使用するいくつかの構成体があります。ほんのわずかな便利さです。また、型宣言が終了するときとメソッド本体宣言を言うときとを微妙に呼び出すこともできると思います。
Eric Lippert、2010年

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タイプを指定しない場合のデフォルトです。私はインターフェースを実装しませんでしたが、それは通常と異なるものを必要としないはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.