2016-04-15 3 views
3

委任:アウト/ refのパラメータは、デリゲートのため

return delegate(IQueryable<MySearchResultItem> query, Expression<Func<MySearchResultItem, object>> lambda, Wrapper wrapper) 
{ 
    wrapper.query = query.OrderBy(lambda); 
    query = query.OrderBy(lambda); 
}; 

ラッパークラス:私はこのデリゲートを実行すると、クエリを変更するために、この関数が終わった後

public class Wrapper 
{ 
    public IQueryable<MySearchResultItem> query { get; set; } 
} 

私は期待が、それはdidnの't。だから、私は、クエリは、(参照ではなく)値によって渡されたと仮定

しかし、私はこのクエリのラッパークラスを作成するときに、ラッパークラスにクエリを追加し、同様にこれを渡します。その後、このメソッドが実行された後、ラッパークラス内のクエリが変更されたため(このラッパークラスは参照渡しされました)

ここでは何が起こっていますか?

+2

あなたはquery.OrderBy(ラムダ)に新たにクエリを割り当てます。新しい参照を作成しないで、入力クエリパラメータが変更されないでしょうか? –

答えて

1

C#の「参照先」とC++の「参照先」を混在させることができます。

コードではqueryが参照渡しされます。つまり、queryの値への参照は値渡しされます。したがって、queryを変更すると、参照が参照している値が変更されます。しかし、参照自体を変更することは何もしません。

queryは変更できません。値を変更する方法はありません。独自の古いクエリを含む新しいクエリのみを作成できます。それはまさに例えばOrderByする - queryは変更されません。これはLINQの中心的な機能の1つで、C#での同様の機能的なアプローチです - 一般的な方法で変更可能なコードは一般的に処理するのがずっと難しいので、特にインターフェイスでそれを避けたいです。

だから、値渡しではなく、参照渡しが必要です。それはまさにあなたがWrapperクラスを提供することによってやったことです。これを行うにはrefというキーワードを使用することもできますが、あなたの場合は完全に不要で対処が難しいです。 refは、参照型であっても有用な場合がありますが、実際には値型にのみ意味があります。彼らはかなり稀です。

しかし、最も簡単で簡単なアプローチは、単純な原則に従うことです。何も変更しないで、変更を含むオブジェクトを返すだけです。むしろ引数を変更するよりも、あなたのデリゲートリターンクエリを、行います

delegate IQueryable<...> YourDelegate(IQueryable<...> query); 

IQueryable<...> YourMethod(IQueryable<...> query) 
{ 
    return query.OrderBy(...); 
} 
1

これは参照渡しですが、参照ではなく、上書きしています。ポインタの値を操作するのではなく、新しいアドレスをポインタに代入すると、Cのようになります。参照を上書きするのではなく、参照で作業するため、ラッパークラスで動作します。

参照を変更する場合は、refオペレータを使用してください。

return delegate(ref IQueryable<MySearchResultItem> query, 

編集:もちろんデリゲートシグネチャに一致しているために必要であり、それがFunc<T1,T2, TResult>では動作しません。

public delegate void MyDelegate(ref IQueryable<object> query, Expression<Func<object, object>> lambda); 

private MyDelegate Create() 
{ 
    return delegate(ref IQueryable<object> query, Expression<Func<object, object>> lambda) 
    { 
     query = query.OrderBy(lambda); 
    }; 
} 
+0

それは私にこのエラーを与えます: "パラメータ1は 'ref'キーワード" – Timon

+0

@Timonで宣言されるべきではありませんもちろん、それを行う*恐ろしいアイデアだからです。他のみんなのように、共通の習慣に従って*新しいクエリを返す*。関数型プログラミングを扱っており、クエリは不変です。新しいものを返し、古いものを変更しないでください。 – Luaan

+0

コードの残りの部分を投稿してください。デリゲートの特定の署名と一致する必要があると仮定します。 – Toxantron

関連する問題