1

I have a method taking an object and returning it in string format with some stuff depending on the type. For example:

ConvertObjectToSQL(1); // "1"
ConvertObjectToSQL("Foo"); // "'Foo'"
ConvertObjectToSQL(DateTime.Now); // "'2017/02/22 00:00:00'"

My problem occurs when I provide an enum to that method. I want my method to act as if I provided it the enum underlying type. Of course, my method is called in a context where I can't possibly know the enum type.

In the first place, here is what I did:

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();
}

But if my enum is:

enum FooEnum : int { Foo = 0, Bar = 1 }

If want :

ConvertObjectToSQL(FooEnum.Foo); // "0"
ConvertObjectToSQL(FooEnum.Bar); // "1"

But it actually returns:

ConvertObjectToSQL(FooEnum.Foo); // "Foo"
ConvertObjectToSQL(FooEnum.Bar); // "Bar"

So I end up with a new else if doing the job:

else if (obj is Enum)
{
    var baseType = Enum.GetUnderlyingType(obj.GetType());
    return Convert.ChangeType(obj, baseType).ToString();
}

My question is: can I avoid reflexion here? Because this methods is called a lots of times.

17
  • try ConvertObjectToSQL(((int)FooEnum.Foo).toString()) Commented Feb 22, 2017 at 9:55
  • @Luminous_Dev: that may not do what is desired if the enum isn't based on int... Commented Feb 22, 2017 at 9:56
  • @Luminous_Dev: as I said: my method is called in a context where I can't possibly know the enum type. So as said @Chris, the enum is not necessarily based on int. Commented Feb 22, 2017 at 9:59
  • 1
    I have to point out a question here though that you should probably not do some of this at all, you're seemingly constructing SQL by concatenating pieces, you may want to look into using parameters instead. Commented Feb 22, 2017 at 10:07
  • 1
    You can always craft delegates and cache these depending on type, this seems to be slightly faster, not by much, but slightly. Commented Feb 22, 2017 at 10:43

2 Answers 2

1

Since enums implement IConvertable we can convert it to a Decimal (which will cover the size all integral types) and then to a string.

private string ConvertObjectToSQL(object obj)
{
    if(obj is Enum)
    {
        return Convert.ToDecimal(obj).ToString();
        //return ((Enum)obj).ToString("D"); Or this
    }
    return "";
}
Sign up to request clarification or add additional context in comments.

10 Comments

That won't work because I do not know the base type of the enum. In my example, I choose int but it could be char for example
Is it legal in IL to have an enum based on char? C# only allows the numeric integral types.
Do you want an numeric value back?
He has already said what he want, he want the numeric value as a string, no matter which underlying type is used for the int, and an int can be based on byte, sbyte, and so on, in which case the cast to (int) will fail.
Why not just use the enum string format specifier "D"?
|
0

You can create a delegate to get the underlying type value and cache it.

''' <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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.