在C#中编译时检查字符串格式

6

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

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

有没有办法实现这个?谢谢。
5个回答

8

你可以通过单元测试来检查值。我的一位同事在一个项目中需要确保某个命名空间中的所有类都应用了特定的属性,因此他做了类似的事情。

在构建过程中运行单元测试(你肯定已经这样做了吧?:)或作为集成构建的一部分。这将使你的源代码更加清晰,而且你不必引入进行断言的代码。


我同意这个观点,我建议也检查一下http://www.postsharp.org/来执行确保/后逻辑。 - kentaromiura
好主意 - 但不幸的是,这些键散布在数万行遗留代码之间 - 绝大部分未被单元测试覆盖。不过我们正朝着目标前进! - roomaroo

2

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

我还会走单元测试路线。由于我认为如果您没有这样做,Settings可能无法在项目外使用,因此您需要在Assembly.cs文件中使用InternalsVisibleTo属性。


1

你真的想在你的应用程序中硬编码这些密钥吗?将它们放在配置文件中岂不更好?这样,如果编译后出现任何问题,那只是一个运行时配置问题。


XML基础存储键名的另一个优点是文件始终可以根据模式进行验证。 - Cerebrus
这些键是指向 XML 文件条目的引用。如果您的所有设置都在配置文件中,仍然需要一种方法来指定要查看哪个设置。 - roomaroo
由于这些似乎是资源文件的键,将它们放入配置中意味着您只需要另一组硬编码字符串来获取这些值。在某个时候,您必须将一个字符串键硬编码到代码中或提供它作为输入,这在这里并不实用。 - Andrew Hare
如果您使用设置文件,则配置元素的键将成为Settings类上的方法,因此将在编译时进行检查。 - Adam Ralph

1

AdamRalph有一点道理,但反方面也是成立的,如果在编译时正确设置,您将永远不会遇到运行时配置问题(假设正确的值不会更改)

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

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


1
如果键的命名遵循与C#标识符相同的规则,或者甚至更加严格和有限,您可以使用枚举:
public enum ResourceKeys
{
    ABC123,
    DEF456
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接