C# 在不知道枚举类型的情况下将枚举基础值转换为字符串
我有一个方法,它获取一个对象并以字符串格式返回它,根据类型的不同,返回一些内容。例如:C# 在不知道枚举类型的情况下将枚举基础值转换为字符串,c#,enums,C#,Enums,我有一个方法,它获取一个对象并以字符串格式返回它,根据类型的不同,返回一些内容。例如: ConvertObjectToSQL(1); // "1" ConvertObjectToSQL("Foo"); // "'Foo'" ConvertObjectToSQL(DateTime.Now); // "'2017/02/22 00:00:00'" 当我向该方法提供枚举时,就会出现问题。我希望我的方法的作用就像我为它提供了枚举基础类型一样。当然,我的方法是在我不可能知道枚举类型的上下文中调用的 首先
ConvertObjectToSQL(1); // "1"
ConvertObjectToSQL("Foo"); // "'Foo'"
ConvertObjectToSQL(DateTime.Now); // "'2017/02/22 00:00:00'"
当我向该方法提供枚举时,就会出现问题。我希望我的方法的作用就像我为它提供了枚举基础类型一样。当然,我的方法是在我不可能知道枚举类型的上下文中调用的
首先,以下是我所做的:
private string ConvertObjectToSQL(object obj)
{
if (obj == null)
{
return "NULL";
}
else if (obj is DateTime)
{
return "'" + obj.ToString() + "'";
}
else if (obj is string)
{
return "'" + obj.ToString().Replace("'", "''") + "'";
}
return obj.ToString();
}
但如果我的枚举是:
enum FooEnum : int { Foo = 0, Bar = 1 }
如果需要:
ConvertObjectToSQL(FooEnum.Foo); // "0"
ConvertObjectToSQL(FooEnum.Bar); // "1"
但它实际上返回:
ConvertObjectToSQL(FooEnum.Foo); // "Foo"
ConvertObjectToSQL(FooEnum.Bar); // "Bar"
因此,如果我做这项工作,我会得到一个新的else:
else if (obj is Enum)
{
var baseType = Enum.GetUnderlyingType(obj.GetType());
return Convert.ChangeType(obj, baseType).ToString();
}
我的问题是:我能在这里避免反射吗?因为这个方法被调用了很多次。因为
枚举
实现了IConvertable
,我们可以将它转换成十进制
(它将覆盖所有整数类型的大小),然后转换成字符串
private string ConvertObjectToSQL(object obj)
{
if(obj is Enum)
{
return Convert.ToDecimal(obj).ToString();
//return ((Enum)obj).ToString("D"); Or this
}
return "";
}
您可以创建一个委托来获取基础类型值并缓存它
''' <summary>
''' Caches an enum underlying value getter delegate.
''' </summary>
''' <typeparam name="TEnum">Enum type</typeparam>
Public Class CachedEnumUnderlyingValueAccess(Of TEnum)
Private Shared underlyingTypeValueGetter As Func(Of TEnum, Object) = CreateUnderlyingTypeValueGetter()
Private Shared Function CreateUnderlyingTypeValueGetter()
Dim enumUnderlyingType As Type = [Enum].GetUnderlyingType(GetType(TEnum))
Dim enumParameter As ParameterExpression = Expression.Parameter(GetType(TEnum))
'Convert the enum parameter to its underlying type, then convert it to an Object
Dim conversionExpression As Expression(Of Func(Of TEnum, Object)) = Expression.Lambda(Expression.Convert(Expression.Convert(enumParameter, enumUnderlyingType), GetType(Object)), enumParameter)
Return conversionExpression.Compile()
End Function
Public Shared Function GetEnumUnderlyingValue(val As TEnum) As Object
Return underlyingTypeValueGetter.Invoke(val)
End Function
End Class
“”
''缓存枚举基础值getter委托。
'''
''枚举类型
公共类CachedEnumUnderingValueAccess(共十个)
私有共享UnderlineTypeValueGetter作为Func(共十个,对象)=CreateUnderlineTypeValueGetter()
私有共享函数CreateUnderlineyTypeValueGetter()
Dim EnumUnderlyngType作为类型=[Enum]。GetUnderlyngType(GetType(TEnum))
Dim enumParameter作为ParameterExpression=Expression.Parameter(GetType(TEnum))
'将枚举参数转换为其基础类型,然后将其转换为对象
Dim conversionExpression As Expression(Of Func(Of TEnum,Object))=Expression.Lambda(Expression.Convert(Expression.Convert(enumParameter,EnumUnderlineType),GetType(Object)),enumParameter)
返回conversionExpression.Compile()
端函数
作为对象的公共共享函数GetEnumUnderlyingValue(val为TEnum)
返回underlineTypeValueGetter.Invoke(val)
端函数
末级
试试ConvertObjectToSQL(((int)FooEnum.Foo).toString())
@leaming\u Dev:如果枚举不是基于int
…@leaming\u Dev:正如我所说:我的方法是在我不可能知道枚举类型的上下文中调用的。正如@Chris所说,枚举不一定基于int。我必须在这里指出一个问题,尽管您可能根本不应该这样做,但您似乎是通过连接片段来构造SQL,您可能需要研究使用参数。您可以根据类型来制作委托并缓存这些委托,这似乎要稍微快一点,不是太快,而是稍微快一点。这不起作用,因为我不知道枚举的基本类型。在我的示例中,我选择int,但它可以是char
,例如,在IL中基于char
的枚举合法吗?C#只允许数值整数类型。你想要返回数值吗?他已经说过他想要的,他想要数值作为字符串,不管int使用哪种基础类型,int可以基于byte、sbyte等,在这种情况下,转换为(int)
将失败。为什么不使用枚举字符串格式说明符“D”?