簡體   English   中英

委托的out / ref參數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM