[英]out / ref parameter for delegate
代表:
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; }
}
當我執行這個委托時,我希望在這個函數結束后更改查詢,但事實並非如此。 所以我假設通過值傳遞的查詢(而不是通過引用)
但是當我為這個查詢創建一個包裝類時,將查詢添加到包裝類中並將其傳遞給它。 然后在完成此方法之后,包裝類中的查詢已更改(因此,此包裝類是通過引用傳遞的?)
這里發生了什么 ?
它通過引用傳遞,但您不是在引用上操作而是覆蓋它。 當你為指針分配一個新地址而不是操作指針的值時,就像在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);
};
}
您可能將C#“引用”與C ++“引用”混合在一起。
在你的代碼, query
是通過引用傳遞,這意味着參考值query
是按值傳遞。 因此,更改query
將更改引用引用的值。 但是,更改引用本身不起作用。
query
是不可變的 - 沒有辦法改變這個值。 您只能創建一個新查詢,其中包含舊查詢。 而這正是OrderBy
所做的 - 它不會改變query
。 這是LINQ和C#中類似功能方法的核心功能之一 - 可變代碼通常難以處理,所以你要避免它,特別是在接口上。
所以你需要做的是通過引用傳遞引用,而不是通過值。 這正是你通過提供Wrapper
類所做的。 也可以使用ref
關鍵字來執行此操作,但這完全沒有必要,而且在您的情況下很難處理。 ref
只對值類型有意義,盡管有一些有用的案例甚至是引用類型; 但是,它們非常罕見。
但最好和最簡單的方法是簡單地遵循簡單的原則:不要改變任何東西,只返回包含變化的對象。 讓您的委托返回查詢,而不是修改參數:
delegate IQueryable<...> YourDelegate(IQueryable<...> query);
IQueryable<...> YourMethod(IQueryable<...> query)
{
return query.OrderBy(...);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.