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

如何解决C#中硬编码字符串过多的代码异味问题?

问题描述

我编写了如下C#代码:

private const string Item1  = "string1";
private const string Item2  = "string2";
private const string Item3  = "string3";

public Handler()
{
    this.itemType = new Dictionary<string, Func<Guid, string, Task<ManagerDto>>>()
    {
        { Item1, Method1 },
        { Item2, Method2 },
        { Item3, Method2 },
    };

    private async Task<ManagerDto> Method1(Guid ownerId, string ownerType)
    {
        return await actionService.GetItem1(ownerId);
    }

    private async Task<ManagerDto> Method2(Guid ownerId, string ownerType)
    {
        switch (ownerType)
        {
            case Item2:
                return await GetItem2.Get(ownerId);

            case Item3:
                return await GetItem3.Get(ownerId);

            default:
                throw new ArgumentException("Invalid thingy");
        }
    }
}

其中Item1有独立处理方法,Item2和Item3共用同一处理方法。此前我将重复的硬编码字符串改为常量,避免修改时需多处维护,但仍被代码评审工具标记为“硬编码值过多”。由于Item1、Item2、Item3为字符串值,无法使用数值类型的enum。作为C#新手,我想知道是否有办法既无需声明这些常量,又能减少硬编码?

解决方案

这里有几种实用的优化方式,既能避免零散常量声明,又能消除硬编码分散的问题:

1. 带描述特性的字符串枚举(类型安全首选)

C#支持给枚举绑定字符串描述,配合扩展方法可以实现“枚举对应目标字符串”的效果,既保留枚举的类型安全,又能满足字符串值的需求:

using System.ComponentModel;
using System.Reflection;

// 定义带字符串描述的枚举
public enum ItemType
{
    [Description("string1")]
    Item1,
    [Description("string2")]
    Item2,
    [Description("string3")]
    Item3
}

// 扩展方法:获取枚举对应的描述字符串
public static class EnumExtensions
{
    public static string GetDescription(this Enum value)
    {
        var field = value.GetType().GetField(value.ToString());
        var attribute = field.GetCustomAttribute<DescriptionAttribute>();
        return attribute?.Description ?? value.ToString();
    }
}

修改后的Handler代码:

public Handler()
{
    this.itemType = new Dictionary<string, Func<Guid, string, Task<ManagerDto>>>()
    {
        { ItemType.Item1.GetDescription(), Method1 },
        { ItemType.Item2.GetDescription(), Method2 },
        { ItemType.Item3.GetDescription(), Method2 },
    };
}

private async Task<ManagerDto> Method2(Guid ownerId, string ownerType)
{
    // 先把传入的字符串转为枚举,再做判断
    if (!Enum.TryParse<ItemType>(ownerType, out var itemType))
    {
        throw new ArgumentException("Invalid thingy");
    }

    switch (itemType)
    {
        case ItemType.Item2:
            return await GetItem2.Get(ownerId);
        case ItemType.Item3:
            return await GetItem3.Get(ownerId);
        default:
            throw new ArgumentException("Invalid thingy");
    }
}

所有字符串值集中维护在枚举特性中,彻底避免零散硬编码,还能获得枚举的类型检查能力。

2. 静态类集中管理字符串

如果不想用枚举,可以把字符串统一放在静态类的只读字段中,比零散常量更规整,代码评审工具通常不会再标记为“硬编码过多”:

public static class ItemStrings
{
    public static readonly string Item1 = "string1";
    public static readonly string Item2 = "string2";
    public static readonly string Item3 = "string3";
}

之后代码中直接用ItemStrings.Item1这类引用即可,所有字符串统一维护在一处,修改时只需改静态类。

3. 直接映射枚举与处理逻辑

彻底摆脱字符串硬编码,把处理逻辑和枚举直接绑定,对外层字符串转枚举的逻辑做统一封装:

public Handler()
{
    // 字典直接用枚举做键,绑定对应的处理方法
    this.itemHandlers = new Dictionary<ItemType, Func<Guid, Task<ManagerDto>>>()
    {
        { ItemType.Item1, actionService.GetItem1 },
        { ItemType.Item2, GetItem2.Get },
        { ItemType.Item3, GetItem3.Get },
    };
}

// 对外暴露的统一处理入口
public async Task<ManagerDto> Handle(Guid ownerId, string ownerType)
{
    if (!Enum.TryParse<ItemType>(ownerType, out var itemType) || !itemHandlers.TryGetValue(itemType, out var handler))
    {
        throw new ArgumentException("Invalid thingy");
    }
    return await handler(ownerId);
}

这种方式内部完全避免了字符串的直接使用,所有逻辑基于枚举展开,类型安全性最高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:42:55