枚举的扩展方法,而不是枚举的实例

发布于 2024-08-24 21:00:12 字数 1021 浏览 3 评论 0原文

我的事物有一个枚举,如下所示:

public enum Things
{
   OneThing,
   AnotherThing
}

我想为此枚举编写一个扩展方法(类似于 Prise 的答案在这里),但是虽然该方法适用于枚举实例,阿拉

Things thing; var list = thing.ToSelectList();

我希望它能够在实际枚举上工作:

var list = Things.ToSelectList();

我可以这样做,

var list = default(Things).ToSelectList();

但我不喜欢它的外观:)

我已经通过以下扩展方法更接近了:

public static SelectList ToSelectList(this Type type)
{
   if (type.IsEnum)
   {
      var values = from Enum e in Enum.GetValues(type)
                   select new { ID = e, Name = e.ToString() };
      return new SelectList(values, "Id", "Name");
   }
   else
   {
      return null;
   }
}

像这样使用:

var list = typeof(Things).ToSelectList();

可以我们还能做得更好吗?

I have an enumeration for my Things like so:

public enum Things
{
   OneThing,
   AnotherThing
}

I would like to write an extension method for this enumeration (similar to Prise's answer here) but while that method works on an instance of the enumeration, ala

Things thing; var list = thing.ToSelectList();

I would like it to work on the actual enumeration instead:

var list = Things.ToSelectList();

I could just do

var list = default(Things).ToSelectList();

But I don't like the look of that :)

I have gotten closer with the following extension method:

public static SelectList ToSelectList(this Type type)
{
   if (type.IsEnum)
   {
      var values = from Enum e in Enum.GetValues(type)
                   select new { ID = e, Name = e.ToString() };
      return new SelectList(values, "Id", "Name");
   }
   else
   {
      return null;
   }
}

Used like so:

var list = typeof(Things).ToSelectList();

Can we do any better than that?

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

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

发布评论

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

评论(7

痴者 2024-08-31 21:00:12

扩展方法仅适用于实例,因此无法完成,但是通过一些精心选择的类/方法名称和泛型,您可以产生看起来同样好的结果:

public class SelectList
{
    // Normal SelectList properties/methods go here

    public static SelectList Of<T>()
    {
        Type t = typeof(T);
        if (t.IsEnum)
        {
            var values = from Enum e in Enum.GetValues(type)
                         select new { ID = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name");
        }
        return null;
    }
}

然后您可以获得这样的选择列表:

var list = SelectList.Of<Things>();

IMO这比 Things.ToSelectList() 读起来要好得多。

Extension methods only work on instances, so it can't be done, but with some well-chosen class/method names and generics, you can produce a result that looks just as good:

public class SelectList
{
    // Normal SelectList properties/methods go here

    public static SelectList Of<T>()
    {
        Type t = typeof(T);
        if (t.IsEnum)
        {
            var values = from Enum e in Enum.GetValues(type)
                         select new { ID = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name");
        }
        return null;
    }
}

Then you can get your select list like this:

var list = SelectList.Of<Things>();

IMO this reads a lot better than Things.ToSelectList().

落花随流水 2024-08-31 21:00:12

不。

你能做的最好的就是将它放在静态类中,如下所示:

public static class ThingsUtils { 
    public static SelectList ToSelectList() { ... }
}

No.

The best you can do is put it on a static class, like this:

public static class ThingsUtils { 
    public static SelectList ToSelectList() { ... }
}
圈圈圆圆圈圈 2024-08-31 21:00:12

Aaronaught的答案真的很棒,基于此我做了以下实现:

public class SelectList
{
    public static IEnumerable<Enum> Of<T>() where T : struct, IConvertible
    {
        Type t = typeof(T);
        if (t.IsEnum)
        {
            return Enum.GetValues(t).Cast<Enum>();
        }
        throw new ArgumentException("<T> must be an enumerated type.");
    }
}

在我看来,它更安全一点,因为你可以 -几乎 - 仅使用枚举来调用它,当然,如果您想要一个无异常版本,您可以简单地返回 null 而不是抛出。

Aaronaught's answer is really great, based on that I made the following implementation:

public class SelectList
{
    public static IEnumerable<Enum> Of<T>() where T : struct, IConvertible
    {
        Type t = typeof(T);
        if (t.IsEnum)
        {
            return Enum.GetValues(t).Cast<Enum>();
        }
        throw new ArgumentException("<T> must be an enumerated type.");
    }
}

In my opinion it's a little bit safer, as you can - almost - call it only with Enums, and of course instead of the throw you can simply return null if you want an exception-free version.

爱你不解释 2024-08-31 21:00:12

我使用“Type”而不是“Enum”来添加扩展。然后我可以从该方法中获取任何类型的列表。这里它返回字符串值:

    public static string[] AllDescription(this Type enumType)
    {
        if (!enumType.IsEnum) return null;

        var list = new List<string>();
        var values = Enum.GetValues(enumType);

        foreach (var item in values)
        {
            // add any combination of information to list here:
            list.Add(string.Format("{0}", item));

            //this one gets the values from the [Description] Attribute that I usually use to fill drop downs
            //list.Add(((Enum) item).GetDescription());
        }

        return list.ToArray();
    }

稍后我可以使用此语法来获取我想要的内容:

var listOfThings = typeof (Things).AllDescription();

I use 'Type' instead of 'Enum' to add extension. Then I can get any type of list back from the method. Here it returns string values:

    public static string[] AllDescription(this Type enumType)
    {
        if (!enumType.IsEnum) return null;

        var list = new List<string>();
        var values = Enum.GetValues(enumType);

        foreach (var item in values)
        {
            // add any combination of information to list here:
            list.Add(string.Format("{0}", item));

            //this one gets the values from the [Description] Attribute that I usually use to fill drop downs
            //list.Add(((Enum) item).GetDescription());
        }

        return list.ToArray();
    }

Later I could use this syntax to get what I want:

var listOfThings = typeof (Things).AllDescription();
Bonjour°[大白 2024-08-31 21:00:12

@Aaronaught 有一个很好的答案。为了扩展他的答案,你甚至可以使其更通用。我在全局库中有这个...

public static IQueryable GetAllEnumValues<T>()
{
    IQueryable retVal = null;

    Type targetType = typeof(T);
    if(targetType.IsEnum)
    {
        retVal = Enum.GetValues(targetType).AsQueryable();
    }

    return retVal;
}

现在您已将此功能与 SelectList 类分离。因此,您可以在 SelectList 方法中或其他任何地方调用它。

public class SelectList
{
    public static SelectList Of<T>
    {
        IQueryable enumValues = GetAllEnumValues<T>();
        var values = 
            from Enum e in enumValues
            select new { ID = e, Name = e.ToString() };
        return new SelectList(values, "Id", "Name");
    }
}

@Aaronaught has a very good answer. To extend his answer, you can also even make it more generic. I have this in a global library...

public static IQueryable GetAllEnumValues<T>()
{
    IQueryable retVal = null;

    Type targetType = typeof(T);
    if(targetType.IsEnum)
    {
        retVal = Enum.GetValues(targetType).AsQueryable();
    }

    return retVal;
}

Now you have de-coupled this functionality from the SelectList class. So you can call this in your SelectList methods, or anywhere else for that matter.

public class SelectList
{
    public static SelectList Of<T>
    {
        IQueryable enumValues = GetAllEnumValues<T>();
        var values = 
            from Enum e in enumValues
            select new { ID = e, Name = e.ToString() };
        return new SelectList(values, "Id", "Name");
    }
}
空宴 2024-08-31 21:00:12

在我看来,这是最干净的方式。为什么?

  • 它适用于任何 System.Enum
  • 扩展方法本身更干净。
  • 要调用它,您只需添加 new ,这是一个小小的权衡(因为它必须有一个实例才能工作。
  • 您没有传递 null ,它实际上是如果您尝试将其与其他类型一起使用,则无法编译。

用法:

(new Things()).ToSelectList()

扩展方法:

[Extension()]
public SelectList ToSelectList(System.Enum source)
{
    var values = from Enum e in Enum.GetValues(source.GetType)
                select new { ID = e, Name = e.ToString() };
    return new SelectList(values, "Id", "Name");    
}

In my opinion, this is the cleanest way. Why?

  • It works for any System.Enum
  • The extension method itself is cleaner.
  • To call it you just add new and that's a small trade off (because it has to have an instance in order to work.
  • You aren't passing null around and it literally won't compile if you try to use it with another type.

Usage:

(new Things()).ToSelectList()

Extension Method:

[Extension()]
public SelectList ToSelectList(System.Enum source)
{
    var values = from Enum e in Enum.GetValues(source.GetType)
                select new { ID = e, Name = e.ToString() };
    return new SelectList(values, "Id", "Name");    
}
我是有多爱你 2024-08-31 21:00:12

我认为,最接近的方法就是对事物进行一些虚拟化,使其像枚举一样工作,而不是枚举。这是我想到的——只是在枚举上放置一个静态方法似乎需要做很多工作,尽管我确实理解它的编程吸引力:

    public class PseudoEnum
{
    public const int FirstValue = 1;
    private static PseudoEnum FirstValueObject = new PseudoEnum(1);

    public const int SecondValue = 2;
    private static PseudoEnum SecondValueObject = new PseudoEnum(2);

    private int intValue;

    // This prevents instantation; note that we cannot mark the class static
    private PseudoEnum() {}

    private PseudoEnum(int _intValue)
    {
        intValue = _intValue;
    }

    public static implicit operator int(PseudoEnum i)
    {
        return i.intValue;
    }

    public static implicit operator PseudoEnum(int i)
    {
        switch (i)
        {
            case FirstValue :
                return FirstValueObject;
            case SecondValue :
                return SecondValueObject;
            default:
                throw new InvalidCastException();
        }
    }

    public static void DoSomething(PseudoEnum pe)
    {
        switch (pe)
        {
            case PseudoEnum.FirstValue:
                break;
            case PseudoEnum.SecondValue:
                break;
        }
    }

}

The closest you can come, I think, is to dummy things up a bit to work like an enum without being one. Here's what I've come up with--it seems like a lot of work just to plop a static method on an enumeration, although I do understand the programming appeal of it:

    public class PseudoEnum
{
    public const int FirstValue = 1;
    private static PseudoEnum FirstValueObject = new PseudoEnum(1);

    public const int SecondValue = 2;
    private static PseudoEnum SecondValueObject = new PseudoEnum(2);

    private int intValue;

    // This prevents instantation; note that we cannot mark the class static
    private PseudoEnum() {}

    private PseudoEnum(int _intValue)
    {
        intValue = _intValue;
    }

    public static implicit operator int(PseudoEnum i)
    {
        return i.intValue;
    }

    public static implicit operator PseudoEnum(int i)
    {
        switch (i)
        {
            case FirstValue :
                return FirstValueObject;
            case SecondValue :
                return SecondValueObject;
            default:
                throw new InvalidCastException();
        }
    }

    public static void DoSomething(PseudoEnum pe)
    {
        switch (pe)
        {
            case PseudoEnum.FirstValue:
                break;
            case PseudoEnum.SecondValue:
                break;
        }
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文