2014-01-08 22 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。它使用它來確定它是否是有效的參數。

相關問題