2014-01-08 20 views
1

我正在使用Visual Studio 2013和.Net 4.5与C#。如何规定方法的参数必须是stringA或stringB

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

我想是这样的:

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

所以,我不能够做到这一点:

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

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

+0

为什么你需要这个呢?如果您可以看到该方法不允许某个值,则不要将该值解析为该方法。 –

+0

感谢您的帮助,我认为这可能是不可能的,我希望@StuartLC的答案,但我需要一个编译错误,只是一个警告是不够的我..我想先使用枚举,但我想用一些也许新的东西:)学习新的东西:) 再次感谢您的所有帮助.. – damir

回答

1

基本上没有。

你可以做

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

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

    // Do something. 
} 

,但是,我会建议其最好使用一个枚举,因为你的状态。

Enum PointlesslyArbritary 
{ 
    A, 
    B 
} 

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

它没有太多的负担,使调用者和编译器的使用更清晰。考虑到,此枚举比您建议的方法“更好”

+0

考虑后,我将使用枚举版本。这也是我的第一选择,但我认为我可以做类似于@StuartLC所说的。但有编译错误。不是每个人都在看警告,所以最好有编译错误。使用枚举,我可以强制方法的用户使用我所能支持的内容。 – damir

2

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

+0

我从这个项目的2个月,并有很多非常类似的枚举那里,和我想,我不会再创建一个新的类似的枚举,但我将不得不这样做,比我想象的要干净得多:) – damir

2

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

0

也想到更好地使用编译时间和创建验证里面的功能。我不知道是否可以使用Attributes来完成您的工作,但是它使用运行时。

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"); 
    } 
} 
+0

是真的,这也是一个很好的观点.. – damir

1

可以使用code contracts使用Contract.Requires

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

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

+0

我从中学到了一些东西,它比“if”或“switch”更容易编写和显示明显的意图。 – Jodrell

+0

我测试过这个,但是这行总是跳过?!并且在悬停中说这个方法调用会被跳过,因为它是有条件的或者有一个没有实现的部分方法?! – damir

+0

@ ku5ar你需要安装合适的VS扩展[VS2010](http://blogs.msdn.com/b/bclteam/archive/2010/01/26/i-just-installed-visual-studio-2010 -now-how-do-i-get-code-contracts-melitta-andersen.aspx)或[2012](http:// stackoverflow。com/questions/13434695/code-contracts-doesnt-seem-to-work-on-vs2012),然后进入'project properties' | '代码合同'选项卡,并选择'执行静态合同检查' – StuartLC

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。它使用它来确定它是否是有效的参数。

相关问题