如何将泛型类型参数限制为 System.Enum

发布于 2024-10-18 13:15:06 字数 934 浏览 0 评论 0原文

可能的重复:
任何人都知道一个好的解决方法缺少枚举通用约束?
创建将 T 约束为枚举的通用方法

可以将泛型类型参数 [我不知道这是否是正确的名称] 限制为 Enum

例如我该如何做这样的事情?

//VB.NET
Function GetValues(Of T As System.Enum)(ByVal value As T) As IEnumerable(Of T)
    Return [Enum].GetValues(value.GetType)
End Function

//C#
public IEnumerable<T> GetValues<T>(T value) where T : System.Enum
{
    return Enum.GetValues(value.GetType());
}

更新

我最终使用了 Jon Skeet 的 无约束的旋律就是为了这个目的。感谢大家的贡献。

Possible Duplicates:
Anyone know a good workaround for the lack of an enum generic constraint?
Create Generic method constraining T to an Enum

Is is possible to limit the generic type parameter [I don't know if that's the right name] to an Enum?

For example how do I do something like this?

//VB.NET
Function GetValues(Of T As System.Enum)(ByVal value As T) As IEnumerable(Of T)
    Return [Enum].GetValues(value.GetType)
End Function

//C#
public IEnumerable<T> GetValues<T>(T value) where T : System.Enum
{
    return Enum.GetValues(value.GetType());
}

Update

I eventually used Jon Skeet's Unconstrained Melody for that purpose. Thanks to you all for your contributions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伴随着你 2024-10-25 13:15:06

你不能。另一种解决方案是使用 struct 和运行时检查。

public IEnumerable<T> GetValues<T>(T value) where T : struct
{  
    if (!typeof(T).IsEnum) throw new NotSupportedException();
    return (IEnumerable<T>)Enum.GetValues(value.GetType()); 
} 

You can't. An alternative solution is using struct and run-time check.

public IEnumerable<T> GetValues<T>(T value) where T : struct
{  
    if (!typeof(T).IsEnum) throw new NotSupportedException();
    return (IEnumerable<T>)Enum.GetValues(value.GetType()); 
} 
清醇 2024-10-25 13:15:06

不幸的是,您不能 - Microsoft 已关闭这是一个无法修复的项目

您可以将枚举视为结构并将其用作约束(我认为 Jon Skeet 在 不受约束的旋律?)但这有点难看。

Unfortunately, you cannot - Microsoft closed this one out as a won't fix item.

You can treat enums as structs and use that as the constraint instead (I think that was how Jon Skeet did it in Unconstrained Melody?) but that is kind of unsightly.

混浊又暗下来 2024-10-25 13:15:06

马特和丹尼的答案都只有一半。这实际上应该满足您的需求:

public IEnumerable<T> GetValues<T>() where T : struct
{   
    if (!typeof(T).IsEnum) throw new InvalidOperationException("Generic type argument is not a System.Enum");
    return Enum.GetValues(typeof(T)).OfType<T>(); 
} 

Danny 答案的更改:

  • 虽然拥有泛型类型的参数允许类型推断,但由于该值实际上并未使用,所以显式指定泛型类型更合适(就像使用 Linq 方法一样)不带参数)。
  • Enum.GetValues() 返回一个对象数组,它不会隐式转换为 T 的 IEnumerable。用于转换结果的额外 Linq 方法(技术上 OfType 是一个过滤操作,但在本例中它将返回所有内容)是必要的符合返回类型。
  • 可选:虽然 NotSupportedException 是抛出异常的一个不错的选择,但还有其他选择; ArgumentException、InvalidOperationException、InvalidCastException 等。我选择 InvalidOperationException 因为它就是这样;从非枚举类型获取枚举值的无效尝试。这是语义上的,我不会与其他人的逻辑争论。

Matt's and Danny's answers both have half the answer. This should actually get you what you need:

public IEnumerable<T> GetValues<T>() where T : struct
{   
    if (!typeof(T).IsEnum) throw new InvalidOperationException("Generic type argument is not a System.Enum");
    return Enum.GetValues(typeof(T)).OfType<T>(); 
} 

Changes from Danny's answer:

  • Though having a parameter of the generic type allows for type inference, since the value is not actually used it is more proper to explicitly specify the generic type (like with the Linq methods that don't take parameters).
  • Enum.GetValues() returns an Array of Objects, which will not cast implicitly to an IEnumerable of T. The extra Linq method to cast the results (technically OfType is a filter operation but in this case it'll return everything) is necessary to conform to the return type.
  • Optional: though NotSupportedException is as good a choice as any for an exception to throw, there are other options; ArgumentException, InvalidOperationException, InvalidCastException, etc. I chose InvalidOperationException because that's what it is; an invalid attempt to get enum values from a non-enum type. This is semantic and I'm not going to argue with anyone else's logic.
天荒地未老 2024-10-25 13:15:06

没有必要以这种方式使您的方法变得通用。

您可以仅使用 System.Enum 作为返回类型中的类型参数:

using System.Linq;
.
.
.
public IEnumerable<Enum> GetValues(Enum value)
{
    return Enum.GetValues(value.GetType()).OfType<Enum>();
}

There is no need to make your method generic in this way.

You can just use the System.Enum as the type parameter in your return type:

using System.Linq;
.
.
.
public IEnumerable<Enum> GetValues(Enum value)
{
    return Enum.GetValues(value.GetType()).OfType<Enum>();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文