2015-10-10 7 views
7

私の知る限り、拡張メソッドのthisref変数として渡されます。私は拡張メソッドとローカル 'this'変数

public static void Method<T>(this List<T> list) 
{ 
    list.Add(default(T)); 
} 

List<int> ints = new List<int>(new int[] { 1, 2, 3, 4, 5 }); 
ints.Method(); 

マイList<int> intsは今1, 2, 3, 4, 5, 0で行うことでこれを確認することができます。私は

public static void Method<T>(this List<T> list, Func<T, bool> predicate) 
{ 
    list = list.Where(predicate).ToList(); 
} 

List<int> ints = new List<int>(new int[] { 1, 2, 3, 4, 5 }); 
ints.Method(i => i > 2); 

を行う際

しかし、私は私のList<int> ints3, 4, 5ことを期待したが手つかずのままでしょう。私は明白な何かを欠いていますか

+0

、それは値渡し参照です。参照を渡すことで、呼び出し元メソッド内の変数が呼び出し先のエイリアスになります。これにより、呼び出し元メソッドに直接割り当てることができます。 – Lee

+0

「渡す*参照」と「渡す* a *参照」には違いがあります。リストへの参照は値渡しです。つまり、リストにアクセスして変更することができますが、リストを参照している外部の変数には触れていません。 –

+0

'(new List ())。メソッド()' compiles =>引数は変数でなくてもよく、 'ref 'のようにはなりません。 –

答えて

5

this拡張メソッドのパラメータは、参照ではなく値によって渡されます。つまり、拡張メソッドに入ると、元のintslistパラメータの2つの変数が同じメモリアドレスを指しています。拡張メソッド内のリストに項目を追加すると、両方の変数によって参照されるオブジェクトを変更するため、intsに反映されます。 listを再割り当てすると、マネージヒープ上に新しいリストが作成され、拡張メソッドのパラメータがこのリストを指しています。 ints変数は引き続き古いリストを指しています。

3

まあ、いくつかのクラスインスタンスのプロパティを変更しようとすると、refは必要ありません。インスタンスを変更するのではなく、インスタンスを変更する必要があるからです。あなたがプロパティを変更すると、あなたがrefキーワードは必要ありません。この例では

class MyClass 
    {    
     public int MyProperty { get; set; } 
    } 

    static void Method(MyClass instance) 
    { 
     instance.MyProperty = 10;      
    } 

    static void Main(string[] args) 
    { 
     MyClass instance = new MyClass(); 
     Method(instance); 

     Console.WriteLine(instance.MyProperty); 
    } 

出力:10

そして、ここであなたはインスタンスと参照していないと動作するのでrefキーワードが必要です。

... 

    static void Method(MyClass instance) 
    { 
     // instance variable holds reference to same object but it is different variable 
     instance = new MyClass() { MyProperty = 10 }; 
    } 

    static void Main(string[] args) 
    { 
     MyClass instance = new MyClass(); 
     Method(instance); 

     Console.WriteLine(instance.MyProperty); 
    } 

出力:0

あなたのシナリオでも同じですが、拡張メソッドは通常の静的メソッドと同じです。メソッド内に新しいオブジェクトを作成すると、refキーワードを使用するか(拡張メソッドではできません)、このオブジェクトを返します。失われた

だから、あなたが使用する必要があり、あなたの第二の場合には:出力

public static List<T> Method<T>(this List<T> list, Func<T, bool> predicate) 
{ 
    return list.Where(predicate).ToList(); 
} 

List<int> ints = new List<int>(new int[] { 1, 2, 3, 4, 5 }); 
ints = ints.Method(i => i > 2); 

foreach(int item in ints) Console.Write(item + " "); 

: `list`は参照渡しされていない3, 4, 5