You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#中普通类与接口的区别及实例赋值的差异与最佳实践

Great questions—let's break these down clearly, since getting a handle on class vs interface differences and reference type behavior is super important in C#.


1. Differences between a regular class and interface in C#

Here are the core distinctions that matter most in practice:

  • Design Intent: Classes are for concrete implementations—they hold state (like fields) and define how things work (methods with actual code). Interfaces are pure contracts—they only say "what a thing can do" via method/property signatures, no implementation or state allowed. Think of interfaces as a job description, and classes as the worker who does the job.
  • Inheritance Rules: A class can inherit from one base class (C# enforces single inheritance for classes), but can implement multiple interfaces. Interfaces, though, can inherit from multiple other interfaces—so you can build composite contracts.
  • Implementation Obligations: When a class implements an interface, it must code every member defined in the interface (unless it's an abstract class, which can leave some unimplemented). For class inheritance, you only override members if you need to change their behavior.
  • Access Modifiers: Interface members are implicitly public—you can't mark them as private or protected. Class members can use any access modifier to control visibility.
  • State & Constructors: Classes can have fields, constructors, destructors, and static members. Interfaces can't have any of these—no state storage, no way to initialize an interface directly.
  • Use Cases: Use classes when you need to create reusable, tangible objects with specific behavior and state. Use interfaces to define common rules across unrelated classes, enabling polymorphism and making your code easier to swap out or test.

2. Assigning an AuthenticationRepository instance to a class vs interface reference

First, let's set up some example code to make this concrete:

// Interface contract
public interface IAuthenticationRepository
{
    bool ValidateUser(string username, string password);
}

// Concrete class implementing the interface
public class AuthenticationRepository : IAuthenticationRepository
{
    // Implemented interface method
    public bool ValidateUser(string username, string password)
    {
        // Actual validation logic here
        return username == "admin" && password == "secure123";
    }

    // Class-specific method NOT in the interface
    public void LogLoginAttempt(string username)
    {
        Console.WriteLine($"Login attempt for {username}");
    }
}

// Creating instances
var classRef = new AuthenticationRepository();
IAuthenticationRepository interfaceRef = new AuthenticationRepository();

What's the visible difference?

  • Accessible Members:
    • classRef lets you call all members of AuthenticationRepository—both the interface's ValidateUser and the class-specific LogLoginAttempt.
    • interfaceRef only exposes members defined in IAuthenticationRepository—you can't call LogLoginAttempt directly (you'd have to cast it back to AuthenticationRepository first, which is risky if the instance isn't actually that type).
  • Polymorphism: The interface reference lets you treat any implementation of IAuthenticationRepository the same way. For example, if you later build a MockAuthenticationRepository for testing, you can swap it into interfaceRef without changing any code that uses the interface.

Is there an essential under-the-hood difference?

Absolutely! Even though both references point to the exact same object in memory, the compiler enforces a "view" of that object based on the reference type. The interface reference restricts you to only the contract defined by IAuthenticationRepository, while the class reference gives you full access to the concrete implementation.

At runtime, the object is still an AuthenticationRepository—the reference type just controls what you can access at compile time, preventing accidental use of class-specific logic when you should be sticking to the agreed-upon contract.

Best Practice

Prefer interface references over concrete class references whenever possible—this is a core part of writing loosely coupled, maintainable code:

  • Flexibility: You can swap out the concrete implementation (e.g., switch from a SQL-based repo to a NoSQL one) without touching code that depends on the interface.
  • Testability: Mocking interfaces is trivial for unit tests—you don't have to deal with the full concrete class's dependencies (like database connections).
  • Clearer Boundaries: Using interfaces makes it explicit which members are part of the public contract consumers should rely on, instead of exposing all internal details of the class.

Only use a concrete class reference when you need access to class-specific members that aren't part of any interface contract.


内容的提问来源于stack exchange,提问作者Ramesh Rajendran

火山引擎 最新活动