【问题标题】:Checking string format at compile time in C#在 C# 编译时检查字符串格式
【发布时间】:2009-02-03 12:27:30
【问题描述】:

在我的代码中,有几个字符串用作访问资源的键。这些键具有特定的格式,例如

string key = "ABC123";

目前,所有这些键都存储为字符串,但我想让事情变得更加健壮和类型安全。理想情况下,我想在编译时检查字符串的格式是否正确。

下一阶段是创建一个从字符串初始化的 ResourceKey 类。然后我可以在运行时检查字符串的格式,例如

ResourceKey key = "ABC123";

其中 ResourceKey 定义为:

using System.Diagnostics;
using System.Text.RegularExpressions;

class ResourceKey
{
    public string Key { get; set; }

    public static implicit operator ResourceKey (string s)
    {
        Debug.Assert(Regex.IsMatch(s, @"^[A-Z]{3}[0-9]{3}$"));
        return new ResourceKey () { Key = s };
    }
}

我真正想做的是有一种编译时断言,这样如果有人试图使用无效的密钥,程序就无法构建。例如

ResourceKey k1 = "ABC123"; // compiles
ResourceKey k2 = "DEF456"; // compiles
ResourceKey k3 = "hello world"; // error at compile time

有什么办法可以做到吗?

谢谢

【问题讨论】:

    标签: c# .net string compiler-construction


    【解决方案1】:

    您可以通过单元测试检查这些值。我的一位同事不得不在一个项目中做类似的事情,我们需要确保某个命名空间中的所有类都应用了某些属性。

    在您的构建中运行单元测试(您这样做对吗?:) 或作为集成构建的一部分。这将使您的源代码更清洁,并且您不必引入执行断言的代码。

    【讨论】:

    • 我同意这一点,我建议也检查postsharp.org 是否执行确保/后逻辑
    • 好主意 - 但不幸的是,这些键分布在数万行遗留代码中 - 绝大多数没有被单元测试覆盖。不过我们快到了!
    【解决方案2】:

    我相信我会添加一个 Settings 类并将它们存储在那里而不是创建一个新类型。 Settings 类可以由应用程序配置文件支持,如果需要,这将使它们更容易通过配置文件更改进行更改。但是,如果您未在配置文件中指定它们,它将使用您设置为默认值的值。

    我也会走单元测试路线。您需要在 Assembly.cs 文件中使用 InternalsVisibleTo 属性,因为如果您不这样做,我认为设置不能在项目之外使用。

    【讨论】:

      【解决方案3】:

      您真的希望将这些密钥硬编码到您的应用中吗?将它们放在配置文件中不是更好吗?那么如果编译后有任何问题,那只是运行时配置问题。

      【讨论】:

      • 基于 XML 的键名存储的另一个优点是始终可以根据 Schema 验证文件。
      • 键是对 XML 文件中条目的引用。如果您的所有设置都在一个配置文件中,您仍然需要一种方法来指定要查看的设置。
      • 因为看起来好像这些是资源文件的键,将它们放在配置中意味着您只需要另一组硬编码字符串来获取这些值。在某些时候,您必须将字符串键硬编码到代码中或将其作为输入提供,这在此处不实用。
      • 如果您使用设置文件,那么配置元素的键将成为设置类上的方法,因此将在编译时进行检查。
      【解决方案4】:

      AdamRalph 有一点,但反点也有效,如果你在编译时做对了,你永远不会遇到运行时配置问题(假设正确的值不能改变)

      除此之外,C# 的编译时间能力绝对是垃圾。它们几乎没有什么可以在编译时完成的。我所知道的最好的可用模板是where 子句。如果我不得不猜测,我会说这是 Anders Hejlsberg 有意的设计选择,因为它似乎与其他语言相匹配

      Andrew Hare 关于单元测试 + 反射的观点与我预期的一样好。我的一个同事用它来测试任何可以在特定情况下使用的类是否正确地实现了某些协议。

      【讨论】:

        【解决方案5】:

        如果键是根据与 C# 标识符相同的规则命名的,或者可能更具限制性、已知且有限,则可以使用枚举:

        public enum ResourceKeys
        {
            ABC123,
            DEF456
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-08
          • 2011-10-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-02
          • 1970-01-01
          • 2019-04-22
          相关资源
          最近更新 更多