C#-返回枚举?来自静态扩展方法

问题描述 投票:2回答:5

我为字符串添加了一些扩展方法,使使用一些自定义枚举变得更加容易。

public static Enum ToEnum<T>(this string s)
{
    return (Enum)Enum.Parse(typeof(T), s);
}

public static bool IsEnum<T>(this string s)
{
    return Enum.IsDefined(typeof(T), s);
}

注意-由于通用类型约束的限制,我必须编写上述方法。我很乐意使用T ToEnum(this string s),其中T:Enum避免在拨打电话后进行强制转换...但是没有办法。

无论如何,我认为最好将此概念扩展一点以返回枚举?在方法签名可以接受各种可为空的枚举的情况下。

public static Enum? ToEnumSafe<T>(this string s)
{
    return (IsEnum<T>(s) ? (Enum)Enum.Parse(typeof(T), s) : null);
}

但是,由于编译器错误,这是不可行的。

error CS0453: The type 'System.Enum' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'

我必须承认我在这里有点儿困惑,例如Enum?应该是合法的返回值,不是吗?我尝试了类似的操作,但最终出现相同的错误。

public static T? ToEnumSafe<T>(this string s)
{
    return (IsEnum<T>(s) ? (T)Enum.Parse(typeof(T), s) : null);
}

我什至决定重写方法以删除泛型,并且得到更多相同的东西:

public static bool IsEnum(this string s, Type T)
{
    return Enum.IsDefined(T, s);
}
public static Enum? ToEnumSafe(this string s, Type T)
{
    return (IsEnum(s, T) ? (Enum)Enum.Parse(T, s) : null);
}

我在这里想念一些真正愚蠢的东西吗?

c# generics enums extension-methods
5个回答
5
投票

尝试:

public static T? ToEnumSafe<T>(this string s) where T : struct
{
    return (IsEnum<T>(s) ? (T?)Enum.Parse(typeof(T), s) : null);
}

3
投票

您实际上可以做得比这更好-要做一些工作。

尽管C#不支持通用约束说T必须是枚举类型,但CLR却支持。我有一个名为Unconstrained Melody的项目,该项目是“与枚举有关的有用事情”的库。我怀疑它已经可以满足您的要求(只要您只需要在枚举中使用names,而不是整数值的字符串表示形式)。尽管它没有IsDefined(string),但确实有TryParse可以完成相同的工作。

请参见this blog post以获取更多详细信息。

关于Enum?不是有效的返回类型的原因-System.Enum本身是引用类型(就像System.ValueType一样),因此它已经可以为空。您只能将?与非空值类型一起使用。


0
投票
public static Enum ToEnum<T>(this string s)
{
    return (Enum)Enum.Parse(typeof(T), s);
}

应该是

public static T ToEnum<T>(this string s)
{
    return (T)Enum.Parse(typeof(T), s);
}

也可以修复以下问题

public static Enum? ToEnumSafe<T>(this string s)
{
    return (IsEnum<T>(s) ? (Enum)Enum.Parse(typeof(T), s) : null);
}

to

public static T? ToEnumSafe<T>(this string s)
    where T : struct
{
    return (IsEnum<T>(s) ? (T?)Enum.Parse(typeof(T), s) : null);
}

0
投票

枚举不是.Net中的唯一类型,它只是具体值类型的占位符(如果没有另外指定,则为int。)>

这意味着您根本不能将其用作类型声明(无论是否使用静态扩展方法)。>>

这实际上是一个非常老的问题,但是从C#7.3 System.Enum通用约束can be used开始,答案可以有所改善。在.NET Core 2中添加的Generic versionEnum.Parse允许解析字符串而无需额外的强制转换

public static T? ToEnum<T>(this string s) where T : struct, Enum
{
    return Enum.IsDefined(typeof(T), s) ? Enum.Parse<T>(s) : default(T?);
}

并且还有一个开放的proposal以改进Enum.IsDefined方法


0
投票

这实际上是一个非常老的问题,但是从C#7.3 System.Enum通用约束can be used开始,答案可以有所改善。在.NET Core 2中添加的Generic versionEnum.Parse允许解析字符串而无需额外的强制转换

© www.soinside.com 2019 - 2024. All rights reserved.