C# 11 中的新的 存取修飾詞:file

在 C# 11 中多了一個新的存取修飾詞(Access Modifier):file
用一句話來解釋就是:使用 file 關鍵字宣告的類別只能在當前檔案中可見。

先來看個範例:
    
public class MyClass
{
    
}

file class MyFileClass
{
    public void MyFileClassMethod()
    {
    }
}
    

上面的範例是放在 MyClass.cs 檔案中,因為 MyFileClass 只在此檔案中可見(partial 也不能),如果不和其他人放在一起就沒有意義了。

筆者最常用來建立輸出 JSON, CSV, XML 這些格式檔案的「定義」類別,因為通常上面都要加很多 Attribute ,而加上 file 關鍵字就只有這個 .cs 檔案可以存取,不怕有其他同名的類別搞混,很方便:
    
public  class MyClass
{
    public string ToJsonString()
    {
        MyFileClass myFileClass = new MyFileClass
        {
            Name = "Ruyut",
            PhoneNumber = "0912345678",
            Email = "a@ruyut.com",
        };
        
        return JsonSerializer.Serialize(myFileClass);
        // {"user-name":"Ruyut","user-phone-number":"0912345678","user-email":"a@ruyut.com"}
    }
}

file class MyFileClass
{
    [JsonPropertyName("user-name")]
    public string? Name { get; set; }
    
    [JsonPropertyName("user-phone-number")]
    public string? PhoneNumber { get; set; }
    
    [JsonPropertyName("user-email")]
    public string? Email { get; set; }
}

    

在一開始使用 file 關鍵字的時候,很容易發現這個問題:
使用 file 存取修飾詞建立的 class 不能被建立為成員變數(member variable)。

錯誤訊息如下:
    
File-local type 'MyFileClass' cannot be used in a member signature in non-file-local type 'MyClass'
    

但多試幾次就會發現其實並不是無法建立成員變數,因為如果是在同樣是使用 file 關鍵字建立的類別中又可以建立成員變數:
    
file class MyFileClass
{
    public void MyFileClassMethod()
    {
    }
}

file class MyFileClass2
{
    MyFileClass myFileClass = new();
}
    

其實重點在於剛剛的錯誤訊息,翻譯成中文是: 「檔案區域型別 'MyFileClass' 無法在非檔案區域型別 'MyClass' 的成員簽章中使用。」
其實意思很簡單,就是因為 file 關鍵字定義的類型只能在當前檔案中使用,如果可能在別的檔案中使用到,那就會跳出錯誤,不讓你用。

不過萬一,假設,可能,如果,我是說如果你一定要這樣做,那其實可以定義為 object ,再透過手動轉型的方式達成:
    
public class MyClass
{
    object _myObject = new MyFileClass();

    public void MyClassMethod(string str)
    {
        ((MyFileClass)_myObject).MyFileClassProperty = str;
    }

    public string MyClassMethod2()
    {
        return ((MyFileClass)_myObject).MyFileClassProperty;
    }
}

file class MyFileClass
{
    public string MyFileClassProperty { get; set; } = "MyFileClassProperty";
}

    



參考資料:
Microsoft.Learn - File-local types
Microsoft.Learn - file (C# Reference)
Microsoft.Learn - Access Modifiers (C# Reference)
Microsoft.Learn - What's new in C# 11

留言

張貼留言

如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com