You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含互斥成员的构造函数及CellCheck类互斥属性技术咨询

处理含互斥属性类的构造函数与属性方案

嘿,这个问题在业务代码里真的很常见——要确保类的属性组合符合业务规则,避免无效配置被误用。我给你几个从易到优的实现方案,兼顾代码安全性和可读性:

方案一:私有构造函数 + 静态工厂方法(推荐)

这种方式能在编译阶段就阻止无效的属性组合,用户只能通过预定义的合法方式创建实例,完全避免误用。

实现代码如下:

enum CellType : byte { Date, Teams, Value, Text }

class CellCheck {
    // 私有构造函数,禁止外部直接实例化
    private CellCheck(CellType cellType) {
        CellType = cellType;
    }

    public CellType CellType { get; } // 设为只读,避免后续修改导致属性失效
    public float? MinValue { get; }
    public float? MaxValue { get; }
    public bool TextCaseSensitive { get; }
    public string Text { get; }

    // 针对每种CellType的静态工厂方法
    public static CellCheck CreateDateCellCheck() {
        return new CellCheck(CellType.Date);
    }

    public static CellCheck CreateTeamsCellCheck() {
        return new CellCheck(CellType.Teams);
    }

    public static CellCheck CreateValueCellCheck(float? minValue = null, float? maxValue = null) {
        // 这里还可以加参数验证,比如minValue <= maxValue
        if (minValue.HasValue && maxValue.HasValue && minValue > maxValue) {
            throw new ArgumentException("MinValue cannot be greater than MaxValue");
        }
        return new CellCheck(CellType.Value) {
            MinValue = minValue,
            MaxValue = maxValue
        };
    }

    public static CellCheck CreateTextCellCheck(string text, bool caseSensitive = false) {
        if (string.IsNullOrEmpty(text)) {
            throw new ArgumentNullException(nameof(text));
        }
        return new CellCheck(CellType.Text) {
            Text = text,
            TextCaseSensitive = caseSensitive
        };
    }
}

使用时直接调用对应工厂方法:

var valueCell = CellCheck.CreateValueCellCheck(minValue: 0, maxValue: 100);
var textCell = CellCheck.CreateTextCellCheck("Hello World", caseSensitive: true);

优点:编译时安全,代码意图清晰,不会出现无效属性组合。

方案二:基于继承的多态设计(更优雅的类型安全方案)

如果不同CellType的逻辑差异较大,把它们拆分成不同的子类会更清晰,每个子类只包含自己需要的属性:

enum CellType : byte { Date, Teams, Value, Text }

// 基类只定义公共属性
abstract class CellCheck {
    public abstract CellType CellType { get; }
}

class DateCellCheck : CellCheck {
    public override CellType CellType => CellType.Date;
}

class TeamsCellCheck : CellCheck {
    public override CellType CellType => CellType.Teams;
}

class ValueCellCheck : CellCheck {
    public override CellType CellType => CellType.Value;
    public float? MinValue { get; set; }
    public float? MaxValue { get; set; }
    // 可以在构造函数里加参数验证
    public ValueCellCheck(float? minValue = null, float? maxValue = null) {
        if (minValue.HasValue && maxValue.HasValue && minValue > maxValue) {
            throw new ArgumentException("MinValue cannot exceed MaxValue");
        }
        MinValue = minValue;
        MaxValue = maxValue;
    }
}

class TextCellCheck : CellCheck {
    public override CellType CellType => CellType.Text;
    public bool CaseSensitive { get; set; }
    public string Text { get; set; }

    public TextCellCheck(string text, bool caseSensitive = false) {
        Text = text ?? throw new ArgumentNullException(nameof(text));
        CaseSensitive = caseSensitive;
    }
}

这种方案的优势是类型本身就代表了合法的配置,完全不存在无效属性的问题,后续扩展新的CellType也很方便(新增子类即可)。

方案三:运行时验证(兼容已有代码的兜底方案)

如果因为历史原因不能修改类的整体结构,只能在构造函数或属性setter里加验证逻辑,确保属性组合合法:

enum CellType : byte { Date, Teams, Value, Text }

class CellCheck {
    private CellType _cellType;
    public CellType CellType {
        get => _cellType;
        set {
            _cellType = value;
            // 切换类型时清空无效属性
            ResetInvalidProperties(value);
        }
    }

    public float? MinValue { get; set; }
    public float? MaxValue { get; set; }
    public bool TextCaseSensitive { get; set; }
    public string Text { get; set; }

    // 构造函数验证
    public CellCheck(CellType cellType) {
        CellType = cellType;
        ResetInvalidProperties(cellType);
    }

    // 额外的验证方法,用于外部设置属性时检查
    public void Validate() {
        switch (CellType) {
            case CellType.Date:
            case CellType.Teams:
                if (MinValue.HasValue || MaxValue.HasValue || TextCaseSensitive || !string.IsNullOrEmpty(Text)) {
                    throw new InvalidOperationException($"CellType {CellType} cannot have MinValue, MaxValue, TextCaseSensitive or Text set");
                }
                break;
            case CellType.Value:
                if (!string.IsNullOrEmpty(Text) || TextCaseSensitive) {
                    throw new InvalidOperationException($"CellType {CellType} cannot have Text or TextCaseSensitive set");
                }
                if (MinValue.HasValue && MaxValue.HasValue && MinValue > MaxValue) {
                    throw new InvalidOperationException("MinValue cannot be greater than MaxValue");
                }
                break;
            case CellType.Text:
                if (MinValue.HasValue || MaxValue.HasValue) {
                    throw new InvalidOperationException($"CellType {CellType} cannot have MinValue or MaxValue set");
                }
                if (string.IsNullOrEmpty(Text)) {
                    throw new InvalidOperationException($"CellType {CellType} requires Text to be set");
                }
                break;
        }
    }

    private void ResetInvalidProperties(CellType cellType) {
        switch (cellType) {
            case CellType.Date:
            case CellType.Teams:
                MinValue = null;
                MaxValue = null;
                TextCaseSensitive = false;
                Text = null;
                break;
            case CellType.Value:
                TextCaseSensitive = false;
                Text = null;
                break;
            case CellType.Text:
                MinValue = null;
                MaxValue = null;
                break;
        }
    }
}

使用时需要记得调用Validate()方法来确保配置合法,或者在属性setter里实时验证。这种方案的缺点是错误只能在运行时发现,但适合无法重构的老项目。

总结建议

  • 优先选静态工厂方法或继承多态,它们能在编译时保证属性组合的合法性,代码更健壮;
  • 如果是老项目无法重构,再用运行时验证作为兜底;
  • 尽量把CellType设为只读,避免后续修改导致属性失效(除非业务允许动态切换类型)。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:44:54