我正在使用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
是否有功能或可能性我可以很好地做到这一点?
答案 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。它使用它来确定它是否是有效参数。