【问题标题】:Cannot convert type 'TEnum' to 'int'无法将类型“TEnum”转换为“int”
【发布时间】:2015-11-17 11:20:31
【问题描述】:

我正在尝试将枚举转换为 this 示例中提到的列表 例如

Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Select(v => new SelectListItem {
    Text = v.ToString(),
    Value = ((int)v).ToString()
}).ToList();

这项工作,但我想修改它以使用通用枚举

public static List<SelectListItem> GetEnumList<TEnum>(TEnum value)
{

        return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Select(v => new SelectListItem
        {
            Text = v.ToString(),
            Value = ((int)v).ToString()
        }).ToList();
 }

但是上面的代码不能编译并给出

无法将类型“TEnum”转换为“int”

换行

  Value = ((int)v).ToString()
  1. 如何修复上面的代码。

  2. 为什么使用通用枚举而不是普通枚举会出现编译错误


编辑:我已经尝试了线程中的建议,但我得到了进一步的错误:

这是我的完整代码:

public static IHtmlContent EnumDropDownListFor<TModel, TResult,TEnum>(
    this IHtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TResult>> expression,
    TEnum enumValue,
    string optionLabel) 
{
    return htmlHelper.DropDownListFor(expression, (IEnumerable<SelectListItem>)GetEnumList(enumValue), optionLabel);
}

public static List<SelectListItem> GetEnumList<TEnum>(TEnum value) 
{
    return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Select(v => new SelectListItem
    {
        Text = v.ToString(),
        Value = Convert.ToInt32(v).ToString()
    }).ToList();

}

但我得到一个运行时错误

ArgumentException:提供的类型必须是枚举。

参数名称:枚举类型

上线

return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Select(v => new SelectListItem
    {
        Text = v.ToString(),
        Value = Convert.ToInt32(v).ToString()
    }).ToList();

我需要在代码中修复什么才能避免出现运行时错误。

【问题讨论】:

  • 您是否尝试将枚举表示的 int 分配给 Value 属性?
  • 先将 TEnum 转换为枚举
  • 重要的是伊万回答中的where ... 子句。将其添加到您的方法中:EnumDropDownListFor(...) where ....

标签: c# linq enums


【解决方案1】:

你没有告诉编译器关于TEnum。就其而言,它可以是字符串、日期时间、银行帐户、子弹或任何东西。

要使其正常工作,您可以使用Enum.ParseConvert.ToInt32

UPD:让我从注释中格式化代码并修复 SO-copy-paasters 的编译错误:D

public static int GetEnumIntValue<T>(T value)
    where T : struct
{
    Type genericType = typeof(T);
    Debug.Assert(genericType.IsEnum);
    Enum enumValue = Enum.Parse(genericType, value.ToString()) as Enum;
    return Convert.ToInt32(enumValue);
}

【讨论】:

  • 你能提供一个例子如何在代码示例中使用 Enum.Parse
  • public static int GetEnumIntValue&lt;T&gt;(T value) where T : struct { Type genericType = typeof(T); Debug.Assert(genericType.IsEnum); Enum enumValue = Enum.Parse(typeof(T), value.ToString()) as Enum; return Convert.ToInt32(test); } google fu 应该很容易发现这一点。
  • 感谢@ColinGrealy!让我格式化您的代码并修复 SO-copy-paasters 的编译错误:D(请参阅编辑后的答案)
【解决方案2】:

您不需要值,只需要枚举类型。你可以使用这样的东西

通用

public static List<SelectListItem> GetEnumList<TEnum>()
    where TEnum : struct, IConvertible, IFormattable
{
    return ((TEnum[])Enum.GetValues(typeof(TEnum))).Select(v => new SelectListItem
    {
        Text = v.ToString(),
        Value = v.ToString("d", null)
    }).ToList();
}

非通用

public static List<SelectListItem> GetEnumList(Type enumType)
{
    return Enum.GetValues(enumType).Cast<IFormattable>().Select(v => new SelectListItem
    {
        Text = v.ToString(),
        Value = v.ToString("d", null)
    }).ToList();
}

这两种方法都不是编译类型安全的。通用,因为缺少枚举约束。非泛型 - 嗯,它类似于 Enum 静态方法,无论如何都不是编译类型安全的。如果以非枚举类型调用,这两种方法都会抛出运行时异常。

【讨论】:

  • 非泛型方法不是编译类型安全的,因为 任何 类型都可以传递给方法,包括非枚举
  • @Ash 正确,但对于通用的相同,因为缺少枚举约束。如果不使用枚举类型调用,两者都可能引发运行时异常。这类似于Enum 方法。
  • 如果我使用通用方式只要添加“where TEnum : struct, IConvertible, IFormattable” 的 where 子句,我的代码将无法编译错误 CS0453 类型 'Type' 必须是非- 可空值类型,以便将其用作泛型类型或方法“MyHelperClass.GetEnumList(TEnum)”中的参数“TEnum”
  • @ozdev 您需要在调用方法中添加相同的约束 - 其中TEnum : struct, IConvertible, IFormattable - 这是最接近当前缺少的enum 约束。如果它在那里,调用方法和泛型方法都将受到where TEnum : enum 的约束。
  • 当我将 where 子句添加到调用方法和被调用方法时,我收到了该错误消息
【解决方案3】:
public static List<SelectListItem> GetEnumList<TEnum>(TEnum value) where TEnum : IConvertible
{
    return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Select(v => new SelectListItem
    {
        Text = v.ToString(),
        Value = v.ToInt32(null).ToString()
    }).ToList();
}
  1. 编译器知道你在.Cast&lt;MyEnum&gt;()之后使用了枚举类型。
  2. 但是在.Cast&lt;TEnum&gt;()之后编译器不知道可以是什么类型。

【讨论】:

  • 我尝试了代码,但我收到“提供的类型必须是枚举”的进一步错误
【解决方案4】:

编译器报错,因为泛型方法中的类型参数不受约束

方法也不必是通用的

public static List<SelectListItem> GetEnumList(Enum value)
{
    return Enum.GetValues(value.GetType())
            .Cast<Enum>()
            .Select(v => new SelectListItem
                        {
                            Text = v.ToString(),
                            Value = Convert.ToInt32(v).ToString()
                        })
            .ToList();
}

如果枚举的基础类型不是int,这仍然可能是一个问题:

public enum LongEnum: ulong
{
    A = 0,
    B = 3000000000
}

// Run-time exception: Value was either too large or too small for an Int32.

【讨论】:

  • 没错,但是你必须用一个值来调用它,而不仅仅是类型。即:GetEnumList(Blah.Test)GetEnumList&lt;Blah&gt;()。它可以工作,但可能会令人困惑,因为根本没有使用 Test
  • @Rob,有问题的方法需要 1 个参数。我没有改变这部分。是的,确实有点不方便,但仅对枚举没有限制
  • 当然——我并没有攻击答案,只是为未来的读者留下评论,如果他们偶然发现的话。真的没有干净的方法来做 OP 什么,所以每种方法都有其缺点。
  • 对于ulong,可以这样解决问题:Value = Convert.ChangeType(v, Enum.GetUnderlyingType(value.GetType())).ToString() :)
  • @Rob,感谢您提供宝贵的 cmets。我测试了你的建议,它按预期工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多