如何从特定参数类强制方法参数为一个?

时间:2018-07-12 08:45:30

标签: c#

首先让我尝试解释一下我的情况。

由于我们无法将字符串值添加到枚举中,并且我不会添加自定义参数类来存储和读取它(出于性能原因,因为如果使用类似: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

如果我将使用枚举,那么这将不是问题,因为方法参数类型已明确定义。

在使用泛型时,我们可以实现这种约束。 有什么我不知道的“轻/快”可以让我这样做吗?

2 个答案:

答案 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}}。这是否是一个问题,以及您如何决定解决这个问题,在很大程度上取决于上下文。