C# 如何对文字字符串参数设置约束
我不得不说,标题太差,无法描述问题,但这是我唯一能想到的。无论如何,假设我得到了以下枚举:C# 如何对文字字符串参数设置约束,c#,constraints,parameter-passing,C#,Constraints,Parameter Passing,我不得不说,标题太差,无法描述问题,但这是我唯一能想到的。无论如何,假设我得到了以下枚举: public enum DocumentType{ IdCard=0, Passport, DriversLicense } 我有一个接受字符串并返回上述枚举的方法: public DocumentType GetDocTypeByString(string docType){ switch (docType) { case "ID":
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#而言,我几乎完全肯定这是不可能的,但我还是决定问。在这种情况下,你会推荐吗?不,你不能。通常使用的模式是抛出一个
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;
}
您可以将返回类型设置为null,并执行如下操作:
public DocumentType? GetDocTypeByString(string docType){
switch (docType)
{
case "ID":
return DocumentType.IdCard;
case "PASS"
return DocumentType.Passport;
//and so on
default: return null;
}
}
这里有几件事你可以做,你选择哪一件取决于你期望这个方法的输入来自哪里。如果获取无效字符串表示程序员出错的情况,那么最好的方法是抛出异常 如果获取无效字符串是一种非常常见(因此也不例外)的情况,例如,如果字符串来自用户输入,您可以通过几种可能的方式更改方法签名,以向使用者明确说明您的方法可能根本不会返回值:
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);
}
public string DocumentType GetDocTypeByString(string docType)
{
文档类型结果;
如果(!tryGetDoctTypeByString(out结果))抛出新的ArgumentException(“docType”);
返回结果;
}
public bool tryGetDoctTypeByString(字符串docType,out DocumentType结果)
{
//您可能应该将其存储为类的静态成员
var-mapping=newdictionary(){
{“ID”,DocumentType.IdCard}
...
};
返回mapping.TryGetValue(docType,out结果);
}
我会这样写:
public bool GetDocTypeByString(string docType, out DocumentType enumValue){
return Enum.TryParse<DocumentType>(docType, true, out enumValue);
}
public bool GetDocTypeByString(string docType,out DocumentType enumValue){
返回Enum.TryParse(docType,true,out enumValue);
}
您可以使用代码契约来指定所需的确切值。它比“if-throw”方法更简洁
这是一个有点晚的答案,主要是我为了好玩而写的,它不优雅也不快速,它只是一个问题的解决方案,我发布代码是为了好玩,看看是否有其他人提出了另一个解决方案,以及某个地方的人可能会看到它,它可能会帮助他们解决类似的问题。免责声明;我不会在生产代码中使用它,它纯粹是为了我自己的享受而编写的
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();
}
}
void Main()
{
字符串p=“通过”;
var c=GetEnumNameByString(p,typeof(DocumentExtendedType));
}
公共枚举文档类型{IdCard=0,Passport,DriversLicense}
公共枚举DocumentExtendedType{ID=0,通过,驱动程序,无}
public TEnum GetEnumNameByString(字符串名称,类型)
{
int index=Enum.Parse(类型、名称).GetHashCode();
如果(枚举已定义(类型(十个),索引))
{
return(TEnum)Enum.GetValues(type).GetValue(index);
}
其他的
{
抛出新的IndexOutOfRangeException();
}
}
我确实相信切换情况更快,因为它不使用反射,尽管这应该适用于任何两个枚举,只要枚举在成员值方面具有相同的结构。这只是解决枚举无法继承的问题的一种方法。在这种情况下,您需要一些值,因此应该抛出异常。Null是许多错误的来源,最好避免这种情况。您从(ui?)获取字符串的地方。您不能使用枚举吗?我可能会通过不让用户输入来确保安全,但我只是好奇。如果情况是ID和IdCard具有相同的名称,而在这个特定的情况下它们没有相同的名称,那么这会起作用。嗯,为什么我不能想到out参数呢。“这是一个很好的例子。@MikeJM我只是在开始玩
Enum.Parse
以查看它抛出了什么异常时才注意到它。