Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Tại sao không thể chỉ định access modifier trong Interface C#?

Lý do thiết kế

Interface là contract (hợp đồng) công khai - định nghĩa "cái gì" class phải làm, không phải "như thế nào". Mục đích: cho phép bên ngoài truy cập qua interface.

  • Interface members mặc định là public (trước C# 8).
  • Không cho phép private, protected, internal trên interface members (trước C# 8).
  • C# 8+ cho phép private, protected, internal cho default implementation.

Trước C# 8: Luôn public


interface IRepository 
{
    void Save();           // Implicit public
    // public void Save(); // ❌ Compile error: "The modifier 'public' is not valid for this item"
    // private void Save(); // ❌ Compile error
}

C# 8+: Default Implementation & Access Modifiers


interface ILogger 
{
    // Public - default, có thể gọi từ interface variable
    void Log(string message) => Console.WriteLine($"[LOG] {message}");
    
    // Private - chỉ dùng nội bộ interface, KHÔNG gọi từ outside
    private void WriteToFile(string msg) 
    {
        File.AppendAllText("log.txt", msg);
    }
    
    // Protected - cho derived interface override
    protected virtual void FormatMessage(ref string msg) 
    {
        msg = $"[{DateTime.Now}] {msg}";
    }
    
    // Internal - chỉ trong assembly
    internal void InternalLog(string msg) { }
    
    // Static members (C# 8+)
    static ILogger() { /* static init */ }
    static void Helper() { }
}

Ví dụ: Private Helper trong Interface


interface ISerializer 
{
    string Serialize(object obj);
    
    // Private helper - không lộ ra ngoài
    private string Escape(string s) => s.Replace("\"", "\\\"");
    
    // Default implementation dùng private helper
    string Serialize(object obj) 
    {
        var json = System.Text.Json.JsonSerializer.Serialize(obj);
        return Escape(json);
    }
}

Interface Access Modifiers (Class level)

Interface type có thể có access modifier:


// Internal interface - chỉ dùng trong assembly
internal interface IInternalService { }

// Public interface - dùng cross-assembly
public interface IPublicService { }

// Private/Protected interface - chỉ trong nested type
class Outer 
{
    private interface IPrivateInterface { }
    protected interface IProtectedInterface { }
}

Explicit Implementation & Access


interface IService 
{
    void Execute();
}

class Service : IService 
{
    // Explicit implementation - implicitly private
    void IService.Execute() 
    {
        Console.WriteLine("Executing...");
    }
}

// Usage
var s = new Service();
// s.Execute(); // ❌ Không thể gọi trực tiếp

IService svc = s;
svc.Execute(); // ✅ Chỉ qua interface

Tóm tắt quy tắc

ContextCho phép modifiersMặc định
Interface members (pre-C# 8)Không cópublic
Interface members (C# 8+) có bodyprivate, protected, internal, staticpublic
Interface members (C# 8+) abstractKhông cópublic
Interface type declarationpublic, internal, private, protected (nested)internal (non-nested)
Explicit implementationKhông cóprivate (implicit)

Tại sao thiết kế như vậy?

  1. Contract clarity: Interface = public API surface.
  2. Substitution principle: Bất kỳ implementer nào đều phải public all members.
  3. Binary compatibility: Thay đổi access modifier = breaking change.
  4. C# 8 default implementations: Private/protected cho implementation details, không phải contract.