如何强制WebSocketClient类实例在实例化时遵循IWebSocketClient接口约束
核心原因
C#的接口约束是编译时类型检查,仅对声明为接口类型的变量生效。你用var接收new WebSocketClient(uri)的返回值时,编译器会直接推断变量类型为WebSocketClient实现类,自然可以访问实现类的所有公开成员,不受IWebSocketClient接口的限制。
可行解决方案
方案1:私有构造+工厂方法返回接口(最推荐,完全杜绝直接实例化实现类)
把WebSocketClient的构造函数设为私有,仅暴露静态工厂方法,返回值强制声明为IWebSocketClient:
public class WebSocketClient : IWebSocketClient { // 构造函数私有,外部无法直接new实例 private WebSocketClient(Uri uri) { } // 对外暴露的静态工厂方法,固定返回接口类型 public static IWebSocketClient Create(Uri uri) { return new WebSocketClient(uri); } /// <inheritdoc /> public WebSocketState State => _webSocket.State; public async Task ConnectAsync(CancellationToken cancellationToken) { // 实现逻辑 } }
使用时即使写var,编译器推断的类型也是IWebSocketClient,无法调用ConnectAsync,完全符合预期:
// 自动推断类型为IWebSocketClient var webSocketClient = WebSocketClient.Create(uri); // 下面的调用会直接编译报错,提示找不到ConnectAsync方法 await webSocketClient.ConnectAsync(CancellationToken.None).ConfigureAwait(false);
方案2:内部类+仅暴露接口(适合类库开发场景)
如果WebSocketClient是类库内部实现,不需要对外暴露,可以把WebSocketClient设为internal,仅对外暴露IWebSocketClient接口和工厂方法:
// 实现类设为internal,仅当前程序集可访问,外部程序集看不到该类型 internal class WebSocketClient : IWebSocketClient { public WebSocketClient(Uri uri) { } // 其余实现省略 } // 对外公开的工厂类 public static class WebSocketFactory { public static IWebSocketClient CreateClient(Uri uri) { return new WebSocketClient(uri); } }
外部程序集根本无法感知WebSocketClient类型的存在,自然不可能用var推断为实现类,只能用接口类型接收实例。
方案3:调整非接口成员的访问级别
如果ConnectAsync本身就不需要对外暴露,直接把它的访问修饰符改为private或internal即可,这样不管变量是什么类型,外部都无法调用该方法。
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

