单个类多构造函数问题:UserKeys类第二个构造函数未被主类识别
解决C#构造函数重载被主类无法识别的问题
先把你的代码格式化一下,方便分析:
abstract class BaseKeys { public abstract bool LeftPressed(); public abstract bool RightPressed(); public abstract bool UpPressed(); public abstract bool DownPressed(); public abstract bool HighHitPressed(); // 建议统一PascalCase命名规范 public abstract bool RopeJumpPressed(); public abstract bool RunRightPressed(); public abstract bool LeftRightPressed(); // 这里你写了override,应该是abstract吧? } class UserKeys : BaseKeys { #region data Keys left, right, up, down, walk; Keys combo, high_hit; #endregion #region ctor public UserKeys(Keys left, Keys right, Keys up, Keys down, Keys high_hit) { this.left = left; this.right = right; this.up = up; this.down = down; this.high_hit = high_hit; } public UserKeys(Keys right, Keys left, Keys down, Keys walk, Keys high_hit) { this.left = left; this.right = right; this.down = down; this.high_hit = high_hit; this.walk = walk; } #endregion // 这里需要实现BaseKeys的所有抽象方法,你代码里没写,不过这是另外的问题 }
你遇到的问题核心是构造函数重载的歧义:两个构造函数都接受5个Keys类型的参数,只是顺序和含义不同。当主类尝试实例化UserKeys时,如果只是按位置传递参数,编译器(或者你用的实例化逻辑,比如反射、DI容器)没办法区分你想调用哪一个,只会匹配第一个符合参数数量的构造函数,导致第二个构造函数看起来“不被识别”。
下面给你几个实用的解决办法:
1. 用命名参数明确指定构造函数
在实例化UserKeys的时候,通过命名参数告诉编译器你要调用哪个构造函数,这样就不会有歧义了。比如调用第二个带walk键的构造函数:
// 明确指定每个参数对应的构造函数参数名 var walkableUserKeys = new UserKeys( right: Keys.D, left: Keys.A, down: Keys.S, walk: Keys.LeftShift, high_hit: Keys.Space );
这种方式简单直接,不需要修改类的结构,适合快速解决问题。
2. 用静态工厂方法替代重载构造函数
把第二个构造函数改成静态工厂方法,语义更清晰,还能避免构造函数重载的混乱。比如:
class UserKeys : BaseKeys { // ... 保留原有的字段和第一个构造函数 ... // 把第二个构造函数改成工厂方法 public static UserKeys CreateWithWalkControl(Keys right, Keys left, Keys down, Keys walk, Keys highHit) { var keys = new UserKeys(); // 可以先加一个私有无参构造函数,或者调整逻辑 keys.left = left; keys.right = right; keys.down = down; keys.high_hit = highHit; keys.walk = walk; return keys; } // 私有无参构造函数,供工厂方法使用 private UserKeys() {} }
调用的时候就可以用:
var walkableUserKeys = UserKeys.CreateWithWalkControl(Keys.D, Keys.A, Keys.S, Keys.LeftShift, Keys.Space);
这种方式的好处是方法名本身就说明了用途,主类调用时一眼就能知道这是创建带walk键的用户配置,可读性更强。
3. 为不同角色创建子类(更符合OOP设计)
既然你是为每个角色创建对应的按键配置,不如直接为不同角色创建子类,每个子类对应自己的构造逻辑,这样主类可以直接依赖不同的子类,完全避免构造函数歧义:
// 普通角色的按键配置 class RegularUserKeys : UserKeys { public RegularUserKeys(Keys left, Keys right, Keys up, Keys down, Keys highHit) : base(left, right, up, down, highHit) { } } // 带walk键的角色按键配置 class WalkableUserKeys : UserKeys { public WalkableUserKeys(Keys right, Keys left, Keys down, Keys walk, Keys highHit) { // 这里直接初始化字段 this.left = left; this.right = right; this.down = down; this.high_hit = highHit; this.walk = walk; } }
主类需要哪个角色的配置,就直接实例化对应的子类,逻辑更清晰,也方便后续扩展不同角色的特殊按键逻辑。
另外提个小建议:C#里方法和属性建议用PascalCase命名(比如HighHitPressed而不是high_hitPressed),字段用camelCase,这样符合.NET的命名规范,代码可读性更高。
内容的提问来源于stack exchange,提问作者Yoav Linder
相关产品推荐
相关产品推荐

