如何指示方法的参数必须是stringS或string

时间:2014-01-08 09:29:33

标签: c# .net visual-studio

我正在使用Visual Studio 2013和.Net 4.5和C#。

是否可以指定方法的参数必须是“stringA”或“stringB”witohut引入具有常量或枚举的新类。当此参数不符合限制时,编译器会收到警告或复制错误。

我想到这样的事情:

public void SomeMethod(string param1) : Allowed param1 = ("stringA" || "stringB")
{
  //Do something.
}

所以我无法做到这一点:

this.SomeMethod("stringC"); <-- this must be a compile error 

是否有功能或可能性我可以很好地做到这一点?

7 个答案:

答案 0 :(得分:2)

我认为(不确定,从未阅读或看过)这是不可能的。但显然您可以处理方法中的所有无效输入并返回无效输入。我不知道为什么你不想在这里介绍枚举,但这将是一个好方法。

答案 1 :(得分:2)

你不能那样做。最好使用枚举或自定义类型作为参数。这将使您的验证在编译时成为可能。

答案 2 :(得分:1)

基本上,没有。

你可以做到

public void SomeMethod(string s)
{
    switch (s)
    {
        case "stringA":
        case "stringB":
            break;

        default:
            throw new ArgumentException("Value invalid.", "s");
    }

    // Do something.
}

但是,我建议你更好地使用enum,就像你说的那样。

Enum PointlesslyArbritary
{
    A,
    B
}

public void SomeMethod(PointlesslyArbritary e)
{
    // Do something.
}

它没有太大的负担,使得调用者和编译器的使用更加清晰。在考虑时,这个枚举比你建议的方法“更好”

答案 3 :(得分:1)

无法检查参数编译时间,因为编译器不知道以下情况会发生什么:

string value = Console.In.Readline();
SomeMethod(value); // How does compile know what is given to SomeMethod

除此之外,如果行为依赖于字符串变量,我会考虑重构或使用正确的错误处理。


3种重构方式:

1:使用枚举:编译时间错误

public enum MyInputEnum { Input1, Input2 }

public void SomeMethod(MyInputInum value) { .. }

SomeMethod(MyInputEnum.Input2); // Compiles
SomeMethod(MyInputEnum.Input3); // Compile Error because Input3 not defined

2:使用接口:编译时间错误

public interface IInputDescription { }
public class InputClass1 : IInputDescription { .. }
public class InputClass2 : IInputDescription { .. }
public class ErrorClass { .. } // This example class does not implement IInputDescription

public void SomeMethod(IInputDescription value) { .. }

SomeMethod(new InputClass2()); // Compiles
SomeMethod(new ErrorClass()); // Compile error

3:使用错误处理:运行时错误

// Option 1
public void SomeMethod(string value)
{
    if(!value.Equals("StringA") && !value.Equals("StringB")) 
        throw new ArgumentException("Invalid argument");
    ...
}

// Option 2
public void SomeMethod(string value)
{
    switch(value)
    {
        case "StringA": 
            ... 
            break;
        case "StringB": 
            ... 
            break;
        default:
            throw new ArgumentException("Invalid argument");
    }
}

答案 4 :(得分:1)

您可以使用Contract.Requires使用code contracts

public void SomeMethod(string param1)
{
   Contract.Requires(param1 == "stringA" || param1 == "stringB");
}

您不一定会收到编译时错误,但如果您打开静态检查,如果调用者与此合同不匹配,您将收到警告。

答案 5 :(得分:0)

还要考虑更好地使用编译时间并在函数内部创建验证。我不知道是否可以使用Attributes来完成你的工作,但它会使用运行时。

答案 6 :(得分:0)

您可以使用某种验证方法让方法知道您要发送的内容,例如:

public enum AllowedParams
{
        StringA = 2,
        StringB = 4,
        StringC = 8,
}

public void SomeMethod(string param1, AllowedParams SentParam)
{
    if (SentParam.HasFlag(AllowedParams.StringA) | SentParam.HasFlag(AllowedParams.StringB))
    {
    }
}

调用这样的方法,

SomeMethod("str", AllowedParams.StringC);

显然这不是你想要的,但C#或.net就此无法做到你想做的事。

编译器不知道将发送给方法的值。这些事情在编译时不会发生,编译器唯一知道的是参数的ParameterInfo。它使用它来确定它是否是有效参数。