Cast problem in a generic method that receives an array of Enum’s (Enum[])

Asked

Viewed 243 times

5

I intend to make a generic method that receives a enum[] and that a string representing the items of array comma-separated.

public static string ToSeparatedCommaString<T>(T[] enums)
    where T : struct, IComparable, IFormattable, IConvertible//Não garante que seja enum mas sempre limita alguma coisa
{
    var commaString = string.Empty;
    foreach (var item in enums)
    {
        commaString += ((Enum)item).GetStringValue() + ",";
    }
    return commaString.TrimEnd(',');
}

The problem arises when I want to access Extension Method GetStringValue().
The attempt to make cast, as expected, is not allowed.

Is there any way to get this?

GetStringValue() is a method that returns a string the value of which is indicated in the attribute associated with the enum

2 answers

6


An easy way to solve the problem is to do the box box of item in a object and then give another cast to the final type Enum.

A few more suggestions:

  • test the type of T to ensure that this is an Enum type, and to release a descriptive exception of the problem that occurred if it is not

  • using LINQ makes the code easier (I think, it’s just a suggestion)

    return string.Join(",", enums.OfType<Enum>().Select(item => item.GetStringValue()));
    

    How did you say that GetStringValue is extension method, can do so too:

    return string.Join(",", enums.OfType<Enum>().Select(NomeDaClasse.GetStringValue));
    

Final code... without using LINQ because it’s a matter of style and it’s personal:

public static string ToSeparatedCommaString<T>(T[] enums)
    where T : struct, IComparable, IFormattable, IConvertible
{
    if (!typeof(T).IsEnum)
        throw new Exception("O método de extensão `ToSeparatedCommaString` suporta apenas Enums no parâmetro genérico `T`.");

    var commaString = string.Empty;
    foreach (var item in enums)
    {
        commaString += ((Enum)(object)item).GetStringValue() + ",";
    }
    return commaString.TrimEnd(',');
}
  • What is extension method is GetStringValue(). The error control was to be added later. In this case it doesn’t make much sense to be extension method because it only applies to enum[].

  • There’s no guarantee that the guy T is Enum. Then the warranty must be via code.

  • I understand... but even if it’s not extension method, it’s still good to check that guy T really be Enum, because if it is not, an exception will occur when doing the type-cast for Enum.

  • Of course, as I said above, this verification was scheduled to be made.

  • I was researching a solution that used Enum.ToObject() but its solution is simpler. I only have the question of why the method exists Enum.ToObject() if the simple cast for Object works.

  • The Enum.ToObject serves to convert an integer into a Enum given the Type of that one: Enum.ToObject(typeof(MeuEnum), 123). The return already leaves Boxed with the type object. This method exists because you will not always have the type of Enum statically, only a Type object.

  • I have improved the LINQ version to make it more readable.

  • 2

    The LINK is more readable to those who dominate it well, which is not yet my case!

  • I took the @bigown test on the LINQ version... it is clearly the most horrible of all... 3.5x slowest. So feel free not to use LINQ!

Show 4 more comments

3

You know that without giving the guarantee, you can not have a reliable code, so you will have to solve at runtime whether it is possible to do the operation or not. There are some possible ways, some better than others, some will give you more power to manipulate the error if it occurs. You can do this:

public static string ToSeparatedCommaString<T>(T[] enums)
    where T : struct, IComparable, IFormattable, IConvertible {
    var commaString = string.Empty;
    if (!typeof(T).IsEnum) {
        throw new ArgumentException("Tipo de enums é inválido");
    }
    foreach (var item in enums) {
        Enum enumerador = item as Enum;
        commaString += enumerador.GetStringValue() + ",";
    }
    return commaString.TrimEnd(',');
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

I made a performance comparison the approach I proposed with Miguel’s response that solves well as well. The result of this was better. This was discussed in the comments below.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.