2011-06-01 5 views
4

私は中の以下の使用方法を見ました:パラメータリストの修飾語の意味は?

Covariance and contravariance real world example

interface IGobbler<in T> { 
    void gobble(T t); 
} 

私はでの使用量が何の略かわかりません。 との関係がありますか? ??

+1

あなたは検索しましたか?検索エンジンが 'in'という単語を取らない場合、' in'の代わりに '+ in'を使う必要があります。 – BoltClock

+0

refは、この文脈で – Jodrell

+0

@BoltClockを適用していないだろう、私は使ってグーグルを検索でした「C#パラメータを中出しrefを」または「パラメータのC#」と有用な情報が返されませんでした。 – q0987

答えて

3

あなたが知っていることは、refoutは無視されています。この場合、inは、Tが機能名の右側にのみ表示されることを意味します(つまり、void gobble(T t)のような仮パラメータリスト)。それがoutと記載されている場合、Tは関数名の左側に表示されます(つまり、戻り値はT foo(int x)など)。デフォルト(何も指定しない)では、いずれの場所にもTが表示されます。

+0

+1。この答えのように。 – JonH

+0

私にとっては、この 'out'はメソッドパラメータリストのoutパラメータを知っていたものとは異なると思われます。これは、関数が返す前に、メソッドがその変数に値を割り当てる必要があることを意味します。 – q0987

+0

@ q0987:はい、それは別の文脈では「out」の使用です。この文脈では、それは関数の仮引数リストに現れます。このコンテキストでは、インタフェースの型パラメータリストに表示されます。 – Gabe

5

4.0内の修飾子は、共分散と反動を強制する(またはむしろ有効にする)必要があります:inout

あなたがinを追加する場合は、あなただけ内側(反変)の位置にTを使用することを許可されている - これが外側(共変)の位置であるとしてAdd(T obj)のようなもので結構ですので、しかしT this[int index] {get;}ではありません。

これは、4.0の分散機能に不可欠です。差異がある場合、refoutはどちらも使用できません(両方とも、そうでない場合はどちらでもありません)。 C#4.0では

+0

インとアウトの説明は分かりやすいです。しかし、私はまだTとインターフェイスIGobbler の間に接続することはできません。私の理解に基づいて、あなたが代理人にメソッドを割り当てるときには、共分散と反変が使用されます。彼の記事に示されているように、彼らはちょうど投影です。また、デリゲートを定義するときにのみインとアウトを指定するのは本当ですか? – q0987

+0

@ q0987いいえ、それは間違っています。デリゲート***またはインターフェイス***。最も顕著なのは 'IEnumerable ' –

+0

です。' IGobbler 'の場合は、そのインタフェースに反差異が強制されます。このルールを破るような "外向きの" API( 'T'を得る方法)を追加させてはいけません。しかし、それは暗黙のcontavariantキャストが可愛いです。差異は完全にオプションです。 –

2

、Contravarianceは、Yは、このたIComparer を達成するためにXの派生 タイプがで修飾子でマークされなければならない場合でもたIComparer <X>は たIComparer <Y>にキャストするために、 たとえばことができます。

public interface IComparer<in T> { 
     public int Compare(T left, T right); 
    } 

てきたが、例示及び説明のためにここを見て:

http://www.csharphelp.com/2010/02/c-4-0-covariance-and-contravariance-of-generics/

2

in修飾子はタイプが反変であると暗黙的に狭い型に変換可能であることを示します。下の例では、ゴブリングがShapeであっても、それはcontravariantと宣言しているので、Action<Rectangle>に割り当てることができます。これは、デリゲートを呼び出してそれをRectangleに渡す人は、明らかにRectangleをShapeをとるメソッドに渡すことができるからです。

inoutを使用する場合にはいくつかのルールがありますが、それは一言で言えば有効です。例えば

public class Shape { } 

public class Rectangle : Shape { } 

public interface IGobbler<Shape> 
{ 
    void gobble(Shape shape); 
} 

public class Gobbler : IGobbler<Shape> 
{ 
    public void gobble(Shape r)  { }  
} 

public static class Program 
{ 
    public static void Main() 
    { 
     var g = new Gobbler(); 

     // notice can implictly convert to a narrower type because of the 'in' keyword 
     Action<Rectangle> r = g.gobble;  
    } 
} 
+0

私は何かが欠けているに違いありません。あなたのコードのどこにでも 'in'は表示されません(コメント内のみ)。 – comecme

+0

@comecme、私はジェームスが単に既存のインターフェイスを使用していると仮定しますIGobbler q0987

+0

私が間違っている場合は私を修正してください。アクション r = g.gobbleを割り当てると、反変が起こります。 Rectangleをg.gobbleに渡すと、共分散が起こります。あれは正しいですか? – q0987

0

INキーワード我々は唯一の入力値としてTを使用するコンパイラに指示します。

これらは、ほとんどの開発者にとって馴染みのメタファーあるように私は、消費と生産と考えるのが好きIGobbler

1

にIGobbler、と言うからキャストできません。飲み込んできゴブラー(消費する)任意の動物はまた、牛を飲み込んできるのでIGobbler<Cow>を取る方法はまた、IGobbler<Animal>を受け入れることができます。ここのゴブラーは、特定の種類の動物の消費者であるため、inタグを使用します。

上記の場合(反差異)は反直感的なように見えるかもしれませんが、を望むRestaurantOwnerの観点から考えてください。もしゴブラーが豚だけを寝かし、レストランオウナーが牛に餌を与えようとするなら、それはうまくいかないでしょう。彼はあまり好きではないゴブラーだけを受け入れることができるので、Gobbler<Animal>またはGobbler<Herbivore>が問題ありません。一方

、動物を販売しているあなたはFarmer<Animal>があると(IEnumerable<Animal>を返すファームメソッドを持つ。)あなたはBuy(IEnumerable<Animal>)したい購入者を持っている場合は、購入者が購入する意思があるとして、それは、Farmer<Cow>.Farm()を受け入れることができます生産された動物や牛はいずれも動物です。ここのFarmerは、特定のタイプのAnimalのプロデューサであるため、 `out 'タグを使用します。

2

内と外はrefとアウトとは何の関係もありません。

ザキーワードにあなたが筈、

​​

はあなたがロバを供給することができるゴブラーを作成ラインを連結例でTのインスタンスを消費するインタフェースのインスタンスでそれを記述するために使用されますドンキーは四倍体ではありませんが、それから派生しています。したがって、引数として基本クラスの代わりにより特殊化されたインスタンスを使用することができます。

outキーワードは、それをcomsumingのではなく、ものを作り出す事を記述するために使われている以外、ほとんど同じように動作します。同じ例で

、ライン

ISpewer<Rodent> rs = new MouseSpewer(); 

が呼び出されたときに、マウスを吐き出すISpewerを作成します。マウスはげっ歯類ではありませんが、それから派生しているので、インターフェースが宣言しているものよりも特殊化されたインスタンスを生成する生成クラスを使用することができます。ほとんどの専門のクラスが2つの場合にスワップされる仕方

注意してください。 inキーワードを使用する場合は、インタフェースの汎用引数として特殊クラスを使用しますが、特殊クラスを作成してもコンパイラに通知するためには、基本クラスを汎用引数として使用します。それを基本クラスのように扱います。

+0

このステートメントの仕組みは? IGobbler dg = new QuadrupedGobbler(); QuadrupedGobblerクラスはインタフェースを実装していますか?実際、これは私が本当に混乱していると感じる場所です。 – q0987

+1

QuadrupedGobblerは一般的なIGobblerインタフェースを実装しています。このインタフェースのシグネチャは、このpublic interface IGobbler ...のように見えますが、IGobblerはIGobblerを実装しているためQuadrupedGobblerを含むことができます。 多型を理解していれば、それほど異質ではない概念です。 –

関連する問題