2017-10-06 71 views
2

我最近在JVM/Groovy领域上几年后回到了.NET世界。类型安全的枚举模式在C#版本6+中仍然可行

我在C#中最喜欢的日常模式之一曾经是Type-Safe enum pattern,我发现非常方便。回到C#我立即开始使用它,但现在我怀疑可能有更好的或者更可取的模式。

让我想到的是我想在“枚举”中引入一些行为。就像这样:

public sealed class TypeSafeEnumWithBehaviour 
{ 
    public static readonly TypeSafeEnumWithBehaviour IsLowerCase = new TypeSafeEnumWithBehaviour("IsLowerCase", s => s.All(c => Char.IsLower(c))); 
    public static readonly TypeSafeEnumWithBehaviour IsUpperCase = new TypeSafeEnumWithBehaviour("IsUpperCase", s => s.All(c => Char.IsUpper(c))); 

    public readonly string Name; 
    public readonly Func<string, bool> IsValid; 

    private TypeSafeEnumWithBehaviour(string targetName, Func<string, bool> validation) 
    { 
     Name = targetName; 
     IsValid = validation; 
    } 

} 

测试:

[TestMethod] 
public void TestMethod1() 
{ 
    Assert.IsTrue(TypeSafeEnumWithBehaviour.IsLowerCase.IsValid("apa")); 
    Assert.IsTrue(TypeSafeEnumWithBehaviour.IsUpperCase.IsValid("PAPA")); 
} 

我organizatoin目前正在使用C#6,而C#7正在成为害得我几个问题更为普遍。

  1. 什么是类型安全枚举模式的当前视图?
  2. 它仍然是一个有效的模式,特别是关于 序列化/持久性?
  3. 我应该放弃它来支持别的吗?
+0

链接是也许不是最权威的,但我认为这说明了模式以及 – Fontanka16

+2

从我透视图,如果你想把枚举引入下一层,最好把它们建模为值对象或枚举类。我知道它在第一眼看起来很奇怪,但至少你可以看一下:https://lostechies.com/jimmybogard/2008/08/12/enumeration-classes/ –

+2

我以前使用过这种模式,但是我不要真的把它们视为“枚举”。在即将到来的语言版本中,我没有看到任何提供这种功能的东西,所以它似乎仍然是一种有效的模式。 –

回答

3

C#(如7.1版本)不支持sum types,所以直到这个解决了,你提供的链接描述的模式应用于作为部分解决静态检查接近世界变问题。您可以查看F#中这种外观的正确语言支持。

你的例子有点奇怪:这些选项并不是真正独特的变体。对于"",它们都持有,因为"Aa"都不成立。他们实际上并没有形成一个独特的可能性集合,所以不清楚为什么称它们为枚举。

小鸡蛋里挑骨头无关的C#7语言的创新:你应该使用nameof这样的考虑:

public static readonly TypeSafeEnumWithBehaviour IsLowerCase = new TypeSafeEnumWithBehaviour(nameof(IsLowerCase), s => s.All(c => Char.IsLower(c)));

+1

你应该清楚'nameof'来自'c#6' –

2

这取决于你想用枚举做什么。

在你的榜样,你要检查的情况下,或许是一个扩展方法会像这样是适当的:

public static bool IsLowerCase(this Enum value) 
{ 
    return value.ToString() == value.ToString().ToLower(); 
} 

这将允许你使用它,像这样:

SomeEnum value = SomeEnums.Test; 
if (value.IsLowerCase()) 
{ 
    DoSomething(); 
} 

要回答您的问题:

  • 类型安全的枚举模式在某些情况下仍然有效,您可能不会w蚂蚁扩展方法或其他方法。
  • 序列化最好通过属性完成,但任何情况都需要根据具体情况进行 - 这太笼统了,不能提供一揽子建议。
  • 只有在有清楚的情况下才放弃它,例如新的语言特征等。当真的使用任何模式时,这是成立的。