2015-05-08 114 views
4

我不得不說,標題太窮,無法描述問題,但這是我能想到的唯一的事情。無論如何,假設我已經給出了以下枚舉:我怎麼能把一個約束力的文字字符串參數

public enum DocumentType{ 
     IdCard=0, 
     Passport, 
     DriversLicense 
} 

而且我有一個接受一個字符串,並返回上述枚舉的方法:

public DocumentType GetDocTypeByString(string docType){ 
    switch (docType) 
    { 
     case "ID": 
     return DocumentType.IdCard; 
     case "PASS" 
     return DocumentType.Passport; 
     //and so on 
    } 
} 

現在,如果傳遞的字符串沒有什麼滿足任何切換條件?最愚蠢的事情是製作返回類型的對象,但這是幾乎沒有人會這樣做的。如果枚舉是我的,我會添加一個名爲「None」的附加值,並在沒有匹配的情況下返回該值,但我無法控制它。然後我想,是否有可能將輸入限制到某些值。就C#而言,我幾乎完全相信這是不可能的,但我仍然決定要問。你會在這種情況下推薦?

+0

你從哪裏購買你的字符串(ui?)。你不能使用枚舉嗎? – Nattrass

+0

我可能會通過不把它留給用戶輸入來保證它的安全,但我只是好奇。 –

回答

5

不,你不能。通常使用的模式是拋出一個

throw new ArgumentException("docType"); 

技術上甚至

throw new ArgumentOutOfRangeException("docType"); 

是正確的,但我還沒有見過它使用外「數字」索引。

例如,如果您使用非法值,則Enum.Parse會拋出ArgumentException,並且您的方法似乎與此非常相似。

其他選項是使用Enum.TryParse模式:

public static bool TryGetDocTypeByString(string docType, out DocumentType documentType) 
{ 
    switch (docType) 
    { 
     case "ID": 
      documentType = DocumentType.IdCard; 
      return true; 
     case "PASS" 
      documentType = DocumentType.Passport; 
      return true; 
    } 

    documentType = default(DocumentType); 
    return false; 
} 
+0

嗯,爲什麼我不能想出參數。這是一個很好的。 –

+0

@MikeJM只有當我開始使用Enum.Parse來查看拋出的異常時,我才注意到它。 – xanatos

4

你可以做的返回類型爲空的,做像這樣:

public DocumentType? GetDocTypeByString(string docType){ 
    switch (docType) 
    { 
     case "ID": 
     return DocumentType.IdCard; 
     case "PASS" 
     return DocumentType.Passport; 
     //and so on 
     default: return null; 
    } 
} 
+0

在這種情況下,你期待有一些價值,所以你應該拋出異常。空是許多錯誤的來源,最好避免這種情況。 –

1

有幾件事情,你可以在這裏做,哪些你選擇哪一個取決於你期望這個方法的輸入來自哪裏。如果獲取無效的字符串表示程序員犯了錯誤,那麼最好的辦法是拋出異常。

如果獲取無效字符串是一種非常常見(因此也不是例外)的情況,例如,如果字符串來自用戶的輸入,可以在幾個可能的方式改變你的方法簽名作出明確到你的方法可能不返回值在所有消費者:

public DocumentType? TryGetDocTypeByString(string docType) { ... } 
public bool TryGetDocTypeByString(string docType, out DocumentType result) { ... } 

最後,你可以結合以上如下方法:

public string DocumentType GetDocTypeByString(string docType) 
{ 
    DocumentType result; 
    if(!TryGetDocTypeByString(out result)) throw new ArgumentException("docType"); 
    return result;    
} 

public bool TryGetDocTypeByString(string docType, out DocumentType result) 
{ 
    // You should probably store this as a static member of your class 
    var mapping = new Dictionary<string, DocumentType>() { 
     { "ID", DocumentType.IdCard } 
     ... 
    }; 

    return mapping.TryGetValue(docType, out result); 
} 
1

這是我會怎麼寫呢:

public bool GetDocTypeByString(string docType, out DocumentType enumValue){ 
      return Enum.TryParse<DocumentType>(docType, true, out enumValue); 
} 
+0

如果情況是ID和IdCard具有相同的名稱,那麼在這種情況下它不適用。 –

0

這是一個有點晚了答案,這是主要的東西,我寫的樂趣,這不是優雅或快,它只是問題的一個解決方案,我張貼的樂趣的代碼和看如果其他人提出了另一種解決方案,並且某個地方有人可能會看到它,這可能會幫助他們解決類似的問題。免責聲明;我不會在生產代碼中使用它,它純粹是爲了我自己的享受而編寫的。

void Main() 
{ 
    string p = "PASS"; 
    var c = GetEnumNameByString<DocumentType>(p, typeof(DocumentExtendedType)); 
} 

public enum DocumentType{ IdCard=0, Passport, DriversLicense } 
public enum DocumentExtendedType { ID = 0, PASS, DRIVERS, NONE } 

public TEnum GetEnumNameByString<TEnum>(string name, Type type) 
{ 
    int index = Enum.Parse(type, name).GetHashCode(); 
    if(Enum.IsDefined(typeof(TEnum), index)) 
    { 
     return (TEnum)Enum.GetValues(type).GetValue(index); 
    } 
    else 
    { 
     throw new IndexOutOfRangeException(); 
    } 
} 

我相信開關罩是更快,因爲它不使用反射,雖然這應該對於任何兩個枚舉工作,只要枚舉具有相同的結構,當涉及到成員的值。這只是一個解決枚舉無法繼承的問題的HACK。

相關問題