簡體   English   中英

C#通用方法類型參數推斷

[英]C# Generic method type argument inference

有什么方法可以概括這里的類型定義嗎? 理想情況下,我希望能夠更改'testInput'的類型,並在編譯時測試正確推斷類型。

public static void Run()
{
    var testInput = 3;
    var test = ((Func<int, int>) Identity).Compose<int,int,int>(n => n)(testInput);
    Console.WriteLine(test);
}

public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
    return x => f(g(x));
}

public static T Identity<T> (this T value)
{
    return value;
}

更新:我可以指定傳遞給Compose的函數的類型,但這仍然指定行中的類型。

public static void Run()
{
    var testInput = 3;
    var identity = (Func<int, int>) Identity;
    var test = identity.Compose((int n) => n)(testInput);
    Console.WriteLine(test);
}

一點背景; 我正在通過Wes Dyer的The Monvel of Monads

好好看,因為我今晚要噴出文字,我會自己捅它。 我應該注意到我不是C#編譯器的專家,我沒有閱讀規范(其中任何一個......對於任何事情),雖然你鏈接的那篇文章真的很有趣,但如果我說我就撒謊是任何一種專家(或者甚至全部100%理解)。

除了警告之外,我對你的問題是:

有什么方法可以概括這里的類型定義嗎?

我認為簡短的回答是否定的。 根據提供的信息,C#編譯器的類型推斷部分根本沒有足夠的信息來從各種變量的使用中推斷出足夠的信息。

正如其他答案所示,它可以簡化。 您可以使用@ Lee的IdentityFunc來允許使用var identity進行類型推斷。 但是,即使添加了這些內容,您的示例代碼仍無法推斷出Compose所有類型變量。

想象一下以下情況:

public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
    return x => f(g(x));
}

public static T Identity<T> (this T value)
{
    return value;
}

public static Func<T, T> IdentityFunc<T>(this T value)
{
    return (Func<T, T>)Identity;
}

public static void Run()
{
    var a = 3; // a is int
    var i = a.IdentityFunc(); // i is Func<int, int>;
    var test = i.Compose(n => n)(a) // test is expected to be int
}

最初,這可能看起來好像應該很容易將test推斷為int 但是, i.Compose的返回類型只能在事實之后從其使用中推斷出來。 C#編譯器顯然不允許這樣做。

public static void Run()
{
    var a = 3; // a is int
    var i = a.IdentityFunc(); // i is Func<int, int>;
    var c = i.Compose(n => n) // c is Func<T, int> - T cannot be resolved without knowledge of n
    var test = c(a); // ideally have type inference infer c (Func<T, int>) as Func<int, int>
}

在該示例中,在的使用ca編譯器將必須回顧性推斷呼叫的返回類型以i.Compose<T, U, V>(n => n)Func<int, int> 這在C#編譯器中顯然是不可能的。 拿掉調用c(a) ,編譯器就不知道c的用法,這將消除任何推斷T可能性(不管怎樣它都可以)。 更高級的類型推理系統可能能夠基於泛型返回的使用來進行這種推斷(可能是F# - 我不是專家的另一個主題)。

由於Wes Dyer沒有提供該特定示例的具體用法,因此不知道是否存在其他一些魔法用於允許您嘗試實現的類型推斷程度。

更像Eric Lippert的合格人員將能夠為您提供更高水平的細節(以及技術准確性/敏銳度)。 我在這里寫了一篇關於類型推理的問題的回復,但我找不到它。 他的博客有很多很棒的信息。 如果您有興趣,可以嘗試聯系他。 此外,他在這里回答這個問題討論monads(並最終鏈接回Wes Dyer的文章)買你可能有興趣閱讀它: Monad用簡單的英語? (對於沒有FP背景的OOP程序員)

您可以編寫一個擴展方法來返回類型的Identity函數:

public static Func<T, T> IdentityFunc<T>(this T value)
{
    return (Func<T, T>)Identity;
}

(或只return v => value;

然后你的測試成了

var testInput = 3; 
var identity = testInput.IdentityFunc();
test = identity.Compose((int n) => n)(testInput);

我能得到的最接近的是顯式輸入n => n lambda的參數:

var test = ((Func<int, int>)Identity).Compose((int n) => n)(testInput);

我認為你不能實現你的理想; C#類型推斷不起作用。

你可能會喜歡F#。

暫無
暫無

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

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