如何创建一个强类型的字符串值集合?
如何创建一个强类型的字符串值集合?
我知道枚举无法作为字符串。
我想要一个具备枚举实用性的数据结构,但是返回的是字符串而不是整数。需要明确的是,我希望返回类型是类似枚举的类型,而不是字符串。基本上,我想要强制一个属性可用作字符串,但只允许设置为预定义的一组字符串值。类似于以下内容:
stringenum Unit { Pixels = "px", Inches = "in" } class Settings { public Unit Unit { get; set; } } var settings = new Settings() { Unit = Unit.Pixels }; ... unitLabel.Text = settings.Unit;
我见过一些解决方案,只是创建一个返回特定字符串的属性的类。然而,我需要返回类型限制为一组特定的字符串,而不仅仅是任意字符串。
编辑以明确问题
考虑上述示例以及以下方法:
public void WriteUnit(Unit unit) { Console.WriteLine(unit); } // 调用 WriteUnit(Unit.Pixels); // 输出 "px" WriteUnit("px"); // 抛出参数异常
如果你传递一个字符串给这个方法,它将抛出一个ArgumentException
。它只接受指定的类型。这正是我所寻找的。
如上所述,您无法直接将枚举映射到字符串。但是,您可以创建一个仅能通过枚举访问的枚举到字符串值的映射。如果您维护这个映射,您可以确保值始终存在。
根据您的附加评论,可以将其与自定义的用户定义的隐式操作符结合使用,以提供您所寻求的功能,尽管您仍然需要调用重写的.ToString()方法来输出字符串。
然后,可以按以下方式使用它:
感谢David。我需要解决的核心问题是,我希望将属性限制为只允许特定的字符串值。这确实允许我使用方法从集合中获取字符串,但无法定义具有限定允许的字符串集合的类型属性。
我不确定我是否理解。如果您重写属性的setter以扩展此用例,您始终可以限制特定属性的允许内容。
所以根据您的答案,我不能给一个类一个类型为Unit的属性,该属性会计算出一个字符串。我必须调用一个基于Unit值的方法来获取字符串。我实际上是在问,如何使一种类型可以像枚举一样返回字符串而不是整数。
或许您可以使用用户定义的转换运算符得到您想要的行为,但它不会是一个枚举。
它不需要是一个枚举,只需要模仿这种行为。我会查看一下!
谢谢您提供的额外细节。我同意,用户定义的转换运算符是正确的方法,但要注意的是,该类型将必须包装Unit,并且您无法隐式扩展字符串,因此您将必须调用ToString。我已经在我的答案中更新了这些细节。
老实说,我认为我不会费心去处理字典开销;将其转换为int并将其用作string[]
的索引会更方便吧?
是的,这是一个遗憾。我真的不想调用ToString()(请参阅我在问题中的编辑)。我认为最终的答案将是C#无法具备这种行为。非常感谢您的帮助。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
那只是利用了字符串格式重写。您可以使用Console.WriteLine($"{unit}");
轻松实现相同的效果。无论哪种情况,都会完全掩盖意图。我同意,这是一个可怕的黑客:)。至少在显式调用.ToString()
时,清楚地表明了您想要做什么。这是一种很好的简化方法,避免了任何外部映射
我发现自己“追逐自己的尾巴”,想要将所有要求压缩到一个类型中...我真的不认为这值得麻烦,而且对客户来说令人惊讶。
我想问题归根结底是我对这门语言的不满。我一直在使用Rust,它允许枚举可以评估为任何您想要的类型,而不仅仅是int,并且仍然提供了强类型的功能。
嗯,有时候您选择工具,有时候您适应功能。但是这里还有一个方法:dotnetfiddle.net/Ocfoub - 使用枚举和扩展方法。
^^我也曾经在Java中遇到过类似的问题。在那里,这也会更容易。但是我学会了实际上喜欢它。如果您被迫将字符串保留在系统的边缘,它会迫使您编写更清晰的代码。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。
这是我对此的尝试:dotnetfiddle.net/8A9Ye4 - 太搞笑了...我不喜欢它。
如果您将输入/输出限制在一系列值范围内,最简单的方法是使用映射来保证。此外,我不知道有任何可以做到您想要做的事情的语言特性。就我所知,这是最接近的方法。