簡體   English   中英

c# 8 switch 表達式:沒有找到 switch 表達式的最佳類型

[英]c# 8 switch expression: No best type was found for the switch expression

我在我的啟動類(.net core 3.1)中添加了一個代碼來返回基於參數的類型,我得到了編譯時錯誤。

我在sharplab中創建了一個運行示例。 如果 switch 表達式包含它運行良好的字符串或其他對象。

工作示例1:

var x = key switch
            {
                "myhandler1" => "something",
                "myhandler2" => "something else",
                _ => "default case"
            };

工作示例2:

object obj =  s switch {
            "a" => new object(),
            "b" => new DateTime(),
            _ => throw new NotImplementedException()
        };

錯誤示例:

interface IHandler { }
public class BaseHandler { }
public class MyHandler1: BaseHandler, IHandler { }
public class MyHandler2: BaseHandler, IHandler { }

class Program
{
    static void Main(string[] args)
    {

        var key = "myhandler1";

        var handler = key switch
        {
            "myhandler1" => new MyHandler1(),
            "myhandler2" => new MyHandler2(),
            _ => throw new NotImplementedException()
        };

        var x = key switch
        {
            "myhandler1" => "something",
            "myhandler2" => "something else",
            _ => "default case"
        };

        Console.WriteLine("Hello World!");
    }
}

原始問題(需要修復):

serviceCollection.AddTransient<Func<string, IHandler>>(sp => key =>
            {
                return key switch
                {
                    Constants.Brand => sp.GetService<Handler1>(),
                    Constants.Series => sp.GetService<Handler2>(),
                    _ => throw new NotImplementedException()

                };
}

找到這個鏈接: https : //github.com/dotnet/csharplang/issues/2728

感謝PavelMarc ,以下是修復:

serviceCollection.AddTransient<Func<string, IHandler>>(sp => key =>
            {
                return key switch
                {
                    Constants.Brand => (sp.GetService<Handler1>() as IHandler),
                    Constants.Series => (sp.GetService<Handler2>() as IHandler),
                    _ => throw new NotImplementedException()

                };
}

您應該顯式聲明一種處理程序類型,而不是var

IHandler handler = key switch //or BaseHandler handler = key switch
{
    "myhandler1" => new MyHandler1(),
    "myhandler2" => new MyHandler2(),
    _ => throw new NotImplementedException()
};

在您的sharplab示例中,兩個處理程序都實現了IHandler接口並繼承了BaseHandler類,編譯器根本不知道使用哪種類型,您應該明確地告訴他

interface IHandler { }
public class BaseHandler { }
public class MyHandler1 : BaseHandler, IHandler { }
public class MyHandler2 : BaseHandler, IHandler { }

依賴注入示例也是如此,你應該顯式聲明一個類型(假設Handler1Handler2實現了IHandler

return key switch
{
    Constants.Brand => sp.GetService<Handler1>(),
    Constants.Series => (IHandler) sp.GetService<Handler2>(),
    _ => throw new NotImplementedException()
};

您只能為一個常量執行此操作,編譯器足夠聰明,可以為您完成其余工作

您正在處理協方差問題。 您已指定Func的返回類型應為IHandler ,但此類型參數是不變的。 因此,您必須實際返回IHandler ,而不僅僅是實現它的類。

serviceCollection.AddTransient<Func<string, IHandler>>(sp => key =>
{
    return key switch
    {
        Constants.Brand => (IHandler)sp.GetService<Handler1>(),
        Constants.Series => (IHandler)sp.GetService<Handler2>(),
        _ => throw new NotImplementedException()
    };
}

var很挑剔 - 它希望事情明確無誤,並且由於MyHandler1MyHandler2是不同的類型,因此這里應該使用什么類型handler並不明顯; 基本上,從MyHandler1MyHandler2選擇一些常見的基類型或實現的接口,並使用它而不是var 在最壞的情況下, object就足夠了:

object handler = key switch
{
    "myhandler1" => new MyHandler1(),
    "myhandler2" => new MyHandler2(),
    _ => throw new NotImplementedException()
};

編譯器不會嘗試自己執行此操作。

暫無
暫無

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

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