首先让我尝试解释一下我的情况。
由于我们无法将字符串值添加到枚举中,并且我不会添加自定义参数类来存储和读取它(出于性能原因,因为如果使用类似:public class StringValueAttribute : Attribute
),所以我决定使用以下类型的类:
public class Permissions
{
public const string X1 = "X1";
public const string X2 = "X2";
public const string X3 = "X3";
....
public const string X43 = "CAN_HAVE A LONG NAME AND NOT FOLLOWING A PATTERN";
}
现在,我想创建一个将字符串作为参数接收的方法。但是,我要强制程序员仅使用strings
中的class Permissions
。
如果我将使用枚举,那么这将不是问题,因为方法参数类型已明确定义。
在使用泛型时,我们可以实现这种约束。 有什么我不知道的“轻/快”可以让我这样做吗?
答案 0 :(得分:1)
我已经多次遇到这种情况。我几乎总是采用struct
方法。
首先,您要定义一个像这样的结构:
public struct Permission : IEquatable<Permission>, IEquatable<string>
{
private readonly string key;
private Permission(string key)
{
this.key = key;
}
// implement Equals, GetHashCode, IEquatable...
}
然后,您可以将所有要拥有的权限声明为该结构的静态成员。
public class Permission
{
// ...
public static readonly First = new Permission("First");
}
现在,使用struct
而不是class
有一个主要优点和一个主要缺点:
default(T)
会这样做。如果您决定使用结构,则强烈建议添加以下方法/属性:
public bool IsEmpty
{
get { return this.key == null; }
}
如果您决定采用类方法,那么分配将大部分保存下来,因为我不认为您将分配新实例(已经声明为静态成员的实例除外),所以缺点实际上是额外的指针。
答案 1 :(得分:0)
不,在该语言中没有什么可以做的。如果您可以避免这种情况,那将是一个很好的选择。当我们有更多背景信息时,我们也许可以提出其他建议。
如果您真的有使用此方法,我建议您首先向该方法添加执行时验证,这样,如果传入无效值,您将立即发现而不是发现处理无效数据。
第二,您可以编写一个Roslyn分析器来查找方法的所有调用,并检查参数是否具有适当的形式。但是,如果您遇到以下情况,可能会导致问题:
public void Foo()
{
FooImpl(Permissions.X1);
DoSomethingElse();
}
private void FooImpl(string permission)
{
RealMethodWithChecking(permission);
}
到那时,您的Roslyn分析器将关闭,因为RealMethodWithChecking
的参数不直接来自Permissions
-而是本身的参数来自{ {1}}。这是否是一个问题,以及您如何决定解决这个问题,在很大程度上取决于上下文。