2016-04-15 56 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; } 
} 

當我執行此委託我預期的要更改的查詢後,這個功能是結束了,但它沒「T。所以我想,通過值(由參考,代替)通過查詢

但是,當我爲這個查詢創建一個包裝類,查詢添加到包裝類,並通過此相伴也。這種方法是做包裝類內的查詢再經過已經被改變(所以這個包裝類是按引用傳遞?)

這是怎麼回事?

+2

您重新分配查詢query.OrderBy(拉姆達)。這不會創建一個新的參考,並且輸入查詢參數因此不會改變? –

回答

1

您可能會將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(...); 
} 
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