簡體   English   中英

強制C#編譯器對Linq Expression參數使用非泛型方法重載

[英]Force C# compiler to use non-generic method overload with Linq Expression parameter

我有重載的方法,一種泛型和一種非泛型。 這兩種方法都將Linq表達式作為單個參數接收:

public void Test(Expression<Action<char>> expr) {}

public void Test<T>(Expression<Func<char, T>> expr) {}

現在考慮以下調用:

var sb = new StringBuilder();
Test(c => sb.Append(c));

因為Append()方法確實(不幸地)返回StringBuilder所以編譯器將選擇通用方法。 但是,就我而言,我絕對需要調用非泛型方法。

以下變通辦法顯示代碼沒有類型問題(非泛型調用將完全有效):

Expression<Action<char>> expr = c => sb.Append(c);
Test(expr);

但是,我寧願不聲明具有顯式類型的變量,而是以某種方式使編譯器選擇非泛型方法(就像我可以告訴它使用具有顯式類型參數的泛型方法一樣)。

您可以在SharpLab.io上玩這個游戲

這似乎是一種解決方法(因為是這樣),但是您可以使用命名參數來闡明您正在調用的方法。

static public void Test(Expression<Action<char>> action) 
{
    Console.WriteLine("Test()");
}

static public void Test<T>(Expression<Func<char, T>> func) 
{
    Console.WriteLine("Test<T>()");
}

當您需要非通用版本時,只需在參數列表中提供參數名稱action:

static public void Main()
{
    var sb = new StringBuilder();
    Test(action: c => sb.Append(c) );
    Test(func: c => sb.Append(c) );
}

輸出:

Test()
Test<T>()

這可能比寫出表達式強制轉換更容易使用。

小提琴

您可以使用空方法吞下sb.Append的返回值。 我不會將其稱為解決方法,因為它只能使編譯器正常工作,但也不是完全干凈漂亮。

static public void NoValue(object value) {}

static public void Test(Expression<Action<char>> action) 
{
    Console.WriteLine("Test()");
}

static public void Test<T>(Expression<Func<char, T>> func) 
{
    Console.WriteLine("Test<T>()");
}

當將輸出包裝為NoValue時,編譯器正確地將其視為Action,而不是函數。

static public void Main()
{
    var sb = new StringBuilder();
    Test(c => NoValue(sb.Append(c)) );
    Test(c => sb.Append(c) );
}

輸出:

Test()
Test<T>()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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