我们可以在c#中定义枚举的隐式转换吗? [英] Can we define implicit conversions of enums in c#?

查看:137
本文介绍了我们可以在c#中定义枚举的隐式转换吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



可以在c#中定义枚举的隐式转换?

  public enum MyEnum 
{
one = 1,two = 2
}

MyEnum number = MyEnum.one;
long i = number;

如果没有,为什么不这样?



有关这方面的进一步讨论和想法,我跟踪了我目前如何处理这个问题:改进C#枚举

解决方案

有一个解决方案。请考虑以下内容:

 公开封闭的类AccountStatus 
{
public static readonly AccountStatus Open = new AccountStatus 1);
public static readonly AccountStatus Closed = new AccountStatus(2);

public static readonly SortedList< byte,AccountStatus> Values = new SortedList< byte,AccountStatus>();
私有readonly字节值;

private AccountStatus(byte value)
{
this.Value = value;
Values.Add(value,this);
}


public static implicit operator AccountStatus(byte value)
{
返回值[byte];
}

public static implicit operator byte(AccountStatus value)
{
return value.Value;
}
}

以上提供隐式转换:

  AccountStatus openedAccount = 1; // Works 
byte openedValue = AccountStatus.Open; // Works

这比宣称一般的枚举更有用处(虽然可以重构一些以上为通用基类)。你可以通过让基类实现IComparable& IEquatable,以及添加方法来返回DescriptionAttributes的值,声明的名称等等。



我写了一个基类(RichEnum)来处理大多数fo咕噜的工作,简化了以上声明的枚举:

 公开密码类AccountStatus:RichEnum< byte,AccountStatus> 
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);

private AccountStatus(byte value):base(value)
{
}

public static implicit operator AccountStatus(byte value)
{
return Convert(value);
}
}

基类(RichEnum)如下所示。 / p>

  using System; 
使用System.Collections.Generic;
使用System.ComponentModel;
使用System.Diagnostics;
使用System.Linq;
使用System.Reflection;
使用System.Resources;

命名空间Ethica
{
using Reflection;
使用文字;

[DebuggerDisplay({Value}({Name}))]
public abstract class RichEnum< TValue,TDerived>
:IEquatable< TDerived>
IComparable< TDerived>
IComparable,IComparer< TDerived>
其中TValue:struct,IComparable< TValue>,IEquatable< TValue>
其中TDerived:RichEnum< TValue,TDerived>
{
#region Backing Fields

///< summary>
///枚举项的值
///< / summary>
public readonly TValue Value;

///< summary>
///公共字段名称,由反射确定
///< / summary>
私有字符串_name;

///< summary>
///将DescriptionAttribute(如果有)链接到声明字段
///< / summary>
private DescriptionAttribute _descriptionAttribute;

///< summary>
///反向查找将值转换回本地实例
///< / summary>
private static SortedList< TValue,TDerived> _values;

private static bool _isInitialized;


#endregion

#region构造函数

protected RichEnum(TValue value)
{
if( _values == null)
_values = new SortedList< TValue,TDerived>();
this.Value = value;
_values.Add(value,(TDerived)this);
}

#endregion

#region属性

public string Name
{
get
{
CheckInitialized();
return _name;
}
}

public string描述
{
get
{
CheckInitialized();

if(_descriptionAttribute!= null)
return _descriptionAttribute.Description;

return _name;
}
}

#endregion

#region初始化

private static void CheckInitialized()
{
如果(!_isInitialized)
{
ResourceManager _resources = new ResourceManager(typeof(TDerived).Name,typeof(TDerived).Assembly);

var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof运算(TDerived));

foreach(字段中的var字段)
{

TDerived instance =(TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetAttribute< DescriptionAttribute>();

var displayName = field.Name.ToPhrase();
}
_isInitialized = true;
}
}

#endregion

#region转换和平等

public static TDerived Convert(TValue value)
{
return _values [value];
}

public static bool TryConvert(TValue value,out TDerived result)
{
return _values.TryGetValue(value,out result);
}

public static implicit operator TValue(RichEnum< TValue,TDerived> value)
{
return value.Value;
}

public static implicit operator RichEnum< TValue,TDerived>(TValue value)
{
return _values [value];
}

public static implicit operator TDerived(RichEnum< TValue,TDerived> value)
{
返回值;
}

public override string ToString()
{
return _name;
}

#endregion

#region IEquatable< TDerived>成员

public override bool Equals(object obj)
{
if(obj!= null)
{
if(obj为TValue)
return Value.Equals((TValue)obj);

if(obj为TDerived)
返回Value.Equals(((TDerived)obj).Value);
}
返回false;
}

bool IEquatable< TDerived> .Equals(TDerived other)
{
return Value.Equals(other.Value);
}


public override int GetHashCode()
{
return Value.GetHashCode();
}

#endregion

#region IComparable会员

int IComparable< TDerived> .CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);


int IComparable.CompareTo(object obj)
{
if(obj!= null)
{
if(obj是TValue)
return Value.CompareTo((TValue)obj);

if(obj为TDerived)
返回值.CompareTo(((TDerived)obj).Value);
}
return -1;
}

int IComparer< TDerived> .Compare(TDerived x,TDerived y)
{
return(x == null)? -1:
(y == null)? 1:
x.Value.CompareTo(y.Value);
}

#endregion

public static IEnumerable< TDerived>值
{
get
{
return _values.Values;
}
}

public static TDerived Parse(string name)
{
foreach(_values.Values中的TDerived值)
if( 0 == string.Compare(value.Name,name,true)|| 0 == string.Compare(value.DisplayName,name,true))
返回值;

返回null;
}
}
}


Is it possible to define an implicit conversion of enums in c#?

something that could achieve this?

public enum MyEnum
{
    one = 1, two = 2
}

MyEnum number = MyEnum.one;
long i = number;

If not, why not?

For further discussion and ideas on this, I followed up with how I currently handle this: Improving the C# enum

解决方案

There is a solution. Consider the following:

public sealed class AccountStatus
{
    public static readonly AccountStatus Open = new AccountStatus(1);
    public static readonly AccountStatus Closed = new AccountStatus(2);

    public static readonly SortedList<byte, AccountStatus> Values = new SortedList<byte, AccountStatus>();
    private readonly byte Value;

    private AccountStatus(byte value)
    {
        this.Value = value;
        Values.Add(value, this);
    }


    public static implicit operator AccountStatus(byte value)
    {
        return Values[byte];
    }

    public static implicit operator byte(AccountStatus value)
    {
        return value.Value;
    }
}

The above offers implicit conversion:

        AccountStatus openedAccount = 1;            // Works
        byte openedValue = AccountStatus.Open;      // Works

This is a fair bit more work than declaring a normal enum (though you can refactor some of the above into a common generic base class). You can go even further by having the base class implement IComparable & IEquatable, as well as adding methods to return the value of DescriptionAttributes, declared names, etc, etc.

I wrote a base class (RichEnum<>) to handle most fo the grunt work, which eases the above declaration of enums down to:

public sealed class AccountStatus : RichEnum<byte, AccountStatus>
{
    public static readonly AccountStatus Open = new AccountStatus(1);
    public static readonly AccountStatus Closed = new AccountStatus(2);

    private AccountStatus(byte value) : base (value)
    {
    }

    public static implicit operator AccountStatus(byte value)
    {
        return Convert(value);
    }
}

The base class (RichEnum) is listed below.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;

namespace Ethica
{
    using Reflection;
    using Text;

    [DebuggerDisplay("{Value} ({Name})")]
    public abstract class RichEnum<TValue, TDerived>
                : IEquatable<TDerived>,
                  IComparable<TDerived>,
                  IComparable, IComparer<TDerived>
        where TValue : struct , IComparable<TValue>, IEquatable<TValue>
        where TDerived : RichEnum<TValue, TDerived>
    {
        #region Backing Fields

        /// <summary>
        /// The value of the enum item
        /// </summary>
        public readonly TValue Value;

        /// <summary>
        /// The public field name, determined from reflection
        /// </summary>
        private string _name;

        /// <summary>
        /// The DescriptionAttribute, if any, linked to the declaring field
        /// </summary>
        private DescriptionAttribute _descriptionAttribute;

        /// <summary>
        /// Reverse lookup to convert values back to local instances
        /// </summary>
        private static SortedList<TValue, TDerived> _values;

        private static bool _isInitialized;


        #endregion

        #region Constructors

        protected RichEnum(TValue value)
        {
            if (_values == null)
                _values = new SortedList<TValue, TDerived>();
            this.Value = value;
            _values.Add(value, (TDerived)this);
        }

        #endregion

        #region Properties

        public string Name
        {
            get
            {
                CheckInitialized();
                return _name;
            }
        }

        public string Description
        {
            get
            {
                CheckInitialized();

                if (_descriptionAttribute != null)
                    return _descriptionAttribute.Description;

                return _name;
            }
        }

        #endregion

        #region Initialization

        private static void CheckInitialized()
        {
            if (!_isInitialized)
            {
                ResourceManager _resources = new ResourceManager(typeof(TDerived).Name, typeof(TDerived).Assembly);

                var fields = typeof(TDerived)
                                .GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
                                .Where(t => t.FieldType == typeof(TDerived));

                foreach (var field in fields)
                {

                    TDerived instance = (TDerived)field.GetValue(null);
                    instance._name = field.Name;
                    instance._descriptionAttribute = field.GetAttribute<DescriptionAttribute>();

                    var displayName = field.Name.ToPhrase();
                }
                _isInitialized = true;
            }
        }

        #endregion

        #region Conversion and Equality

        public static TDerived Convert(TValue value)
        {
            return _values[value];
        }

        public static bool TryConvert(TValue value, out TDerived result)
        {
            return _values.TryGetValue(value, out result);
        }

        public static implicit operator TValue(RichEnum<TValue, TDerived> value)
        {
            return value.Value;
        }

        public static implicit operator RichEnum<TValue, TDerived>(TValue value)
        {
            return _values[value];
        }

        public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
        {
            return value;
        }

        public override string ToString()
        {
            return _name;
        }

        #endregion

        #region IEquatable<TDerived> Members

        public override bool Equals(object obj)
        {
            if (obj != null)
            {
                if (obj is TValue)
                    return Value.Equals((TValue)obj);

                if (obj is TDerived)
                    return Value.Equals(((TDerived)obj).Value);
            }
            return false;
        }

        bool IEquatable<TDerived>.Equals(TDerived other)
        {
            return Value.Equals(other.Value);
        }


        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        #endregion

        #region IComparable Members

        int IComparable<TDerived>.CompareTo(TDerived other)
        {
            return Value.CompareTo(other.Value);
        }

        int IComparable.CompareTo(object obj)
        {
            if (obj != null)
            {
                if (obj is TValue)
                    return Value.CompareTo((TValue)obj);

                if (obj is TDerived)
                    return Value.CompareTo(((TDerived)obj).Value);
            }
            return -1;
        }

        int IComparer<TDerived>.Compare(TDerived x, TDerived y)
        {
            return (x == null) ? -1 :
                   (y == null) ? 1 :
                    x.Value.CompareTo(y.Value);
        }

        #endregion

        public static IEnumerable<TDerived> Values
        {
            get
            {
                return _values.Values;
            }
        }

        public static TDerived Parse(string name)
        {
            foreach (TDerived value in _values.Values)
                if (0 == string.Compare(value.Name, name, true) || 0 == string.Compare(value.DisplayName, name, true))
                    return value;

            return null;
        }
    }
}

这篇关于我们可以在c#中定义枚举的隐式转换吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆