如果你是 .NET 開發者,考個簡單問題:

.NET 6+ 寫的程式可以直接參照引用 .NET Framework 編譯的 DLL 嗎?
(註:非 .NET Standard,純 .NET Framework 2.0/3.5/4.0/4.5 ~ 4.8,參考:淺談 .NET 類別程式庫跨平台開發)

我答錯了。

在我的印象中,.NET Framework 寫的專案必須轉成 .NET 6+ 或 .NET Standard 才能供 .NET 6+ (過去叫 .NET Core) 叫用。前幾天幫看問題,大驚! 事情怎麼跟我想得不一樣。如下圖範例,.NET 8 Console Application 居然直接參照 .NET Framework 4.8 寫的類別程式庫(實際案例是參照 .NET 2.0 跟 .NET 3.5 寫的程式庫),程式編譯成功,執行正常。

為此爬文,補齊一些知識。

相關文件在此 - .NET Framework 相容性模式

.NET Standard 2.0 起加入了 .NET Framework 相容性模式,允許 .NET Standard 和 .NET Core 專案參考 .NET Framework 程式庫。但有個陷阱,並非所有專案都適用,如果 .NET Framework 程式庫用到 .NET 6+ 或 .NET Standard 不支援的 API,程式將會出錯,而且是編譯過程一片祥和,等執行階段再炸裂。

例如:我在 .NET 4.8 類別故意用了 .NET Core 不支援的另建 AppDomain、System.Web.Services.WebService (延伸閱讀:.NET 6+ 無法使用的 .NET Framework 技術)

using System;

namespace NetFXLib
{
    public class Foo
    {
        public string SayHello() 
            => "Hello from .NET Framework Class Library";

        public string TestAppDomain()
            => AppDomain.CreateDomain("TestAppDomain").FriendlyName;

        public string TestWebService()
        {
            var ws = new System.Web.Services.WebService();
            return ws.GetType().FullName;
        }
    }
}

.NET 8 Console Program.cs 長這樣:

var foo = new NetFXLib.Foo();
TryRun(() => Console.WriteLine(foo.SayHello()));
TryRun(() => Console.WriteLine(foo.TestAppDomain()));
TryRun(() => Console.WriteLine(foo.TestWebService()));

void TryRun(Action action)
{
    try
    {
        action.Invoke();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"ERROR - {ex.Message}");
    }
}

編譯沒問題,但執行時新增 AppDomain 及引用 System.Web.Services 相關型別的功能會出錯:

dotnet publish -r linux-x64 --no-self-contained 丟到 Linux 執行,結局相同:

相當然爾,若直接在 Linux 嘗試編譯,因 NetFXLib 是 .NET Framework 專案,是不可能成功的!

但若改成直接參照編譯好的 .NET Framework DLL,倒是可以成功編譯,但該出錯的還是要出錯。

由此可知,雖然 .NET 6+ 可以參照 .NET Framework DLL,但可能出現執行階段才冒出來的不相容錯誤,不能算是可靠的做法,等同失去 .NET 在編譯階段揪出錯誤的強型別優勢。故原則上還是建議將專案升級成 .NET 6+ 或 .NET Standard,會是較嚴謹可信賴的做法。

要將 .NET Framework 專案升級成 .NET 6+/.NET Standard 專案,微軟有個 .NET Upgrade Assistant 能協助升級,可多加利用。

A discussion on whether a .NET 6+ program can directly reference .NET Framework library.


Comments

# by Ho.Chun

.net standard 跟 .net framework / .net core 有什麼關係 ?

# by Jeffrey

to Ho.Chun, 文章開頭有篇 淺談 .NET 類別程式庫跨平台開發,裡面有較詳細的說明。

Post a comment