枚举类型 "Inheritance"

475

我在一个低层命名空间中有一个枚举。我想在一个中级命名空间中提供一个类或枚举,该类或枚举“继承”低级别枚举。

namespace low
{
   public enum base
   {
      x, y, z
   }
}

namespace mid
{
   public enum consume : low.base
   {
   }
}

我希望这是可能的,或者有一种类可以替代枚举“consume”,为枚举提供一层抽象,但仍然让该类的实例访问枚举。

你有什么想法吗?

编辑: 我没有将其切换为类中的常量的其中一个原因是,必须使用低级别的枚举来消耗一个服务。我已经获得了WSDL和XSD,它们将结构定义为枚举。该服务不能更改。


1
一个选项是 https://www.codeproject.com/Articles/20805/Enhancing-C-Enums - Walter Verhoeven
1
你可以使用Int32,并根据需要将其强制转换为枚举类型。 - Dan Csharpster
你可以使用代码脚本。阅读原始代码并创建新代码。我有工作流和工作流过滤器。它们除了一个ALL值之外是相同的。我只需使用脚本来创建具有所有值的新工作流过滤器。请参见T4。虽然不在语言中,但总有办法。 - KenF
17个回答

1
另一个可能的解决方案:

public enum @base
{
    x,
    y,
    z
}

public enum consume
{
    x = @base.x,
    y = @base.y,
    z = @base.z,

    a,b,c
}

// TODO: Add a unit-test to check that if @base and consume are aligned

HTH


1
这是不可能的(如@JaredPar已经提到的)。尝试通过逻辑来解决这个问题是一种不好的做法。如果您有一个具有枚举的基类,应该在那里列出所有可能的枚举值,并且类的实现应该使用它所知道的值。
例如,假设您有一个基类BaseCatalog,它有一个枚举ProductFormats(Digital、Physical)。然后您可以拥有MusicCatalog或BookCatalog,它可以包含Digital和Physical产品,但如果类是ClothingCatalog,则只能包含Physical产品。

1

枚举并不是实际的类,即使它们看起来像。在内部,它们只是像它们底层类型一样被处理(默认为Int32)。因此,您只能通过将单个值从一个枚举“复制”到另一个枚举,并将它们转换为其整数值以进行比较相等性。


1

枚举类型不能从其他枚举类型派生,只能从 int、uint、short、ushort、long、ulong、byte 和 sbyte 派生。

就像 Pascal 所说的那样,您可以使用其他枚举类型的值或常量来初始化枚举类型的值,但仅限于此。


8
因为C#语法的原因,枚举类型被称为一种误导性的叫法,但实际上它们并不能从int、uint等类型继承。在底层,它们仍然是从System.Enum继承。只不过代表枚举类型的成员被指定为int、uint等类型。 - JaredPar
@JaredPar。当枚举从uint派生时,这意味着它的值都是uint,等等。默认情况下,枚举继承int。(看一下C#规范,枚举SomeEnum:uint {...}实际上是有效的。) - Jeroen Landheer
4
实际上不是这样的。它继承自System.enum。正如之前在此处经常提到的那样,你认为的继承只是C#中的语言模糊性。 - TomTom

0
根据您的情况,您可能不需要派生枚举,因为它们是基于 System.Enum 的。
使用此代码,您可以传递任何喜欢的枚举并获取其选定值:
public CommonError FromErrorCode(Enum code)
{
    Code = (int)Enum.Parse(code.GetType(), code.ToString());

0
如果需要的话,您可以实现自己的类结构,其中包括您从继承枚举的概念中想要的功能,还可以添加更多功能。 您只需实现相等比较器和查找值的函数即可轻松编写代码。 将构造函数设置为私有,并声明该类及其任何子类的静态实例,以任何程度都可以。 或者找到一个简单的解决方案来解决您的问题,并坚持使用本机枚举实现。
继承枚举的代码重型实现:
/// <summary>
/// Generic Design for implementing inheritable enum
/// </summary>
public class ServiceBase
{

    //members
    protected int _id;
    protected string _name;

    //constructors
    private ServiceBase(int id, string name)
    {
        _id = id;
        _name = name;
    }

    //onlu required if subclassing
    protected ServiceBase(int id, string name, bool isSubClass = true )
    {
        if( id <= _maxServiceId )
            throw new InvalidProgramException("Bad Id in ServiceBase" );
        _id = id;
        _name = name;
        
    }

    //members
    public int Id => _id;
    public string Name => _name;
    public virtual ServiceBase getService(int serviceBaseId)
    {
        return ALLBASESERVICES.SingleOrDefault(s => s.Id == _id);
    }
    
    //implement iComparable if required
    
    //static methods
    public static ServiceBase getServiceOrDefault(int serviceBaseId)
    {
        return SERVICE1.getService(serviceBaseId);
    }

    //Enumerations Here
    public static ServiceBase SERVICE1 = new ServiceBase( 1, "First Service" );
    public static ServiceBase SERVICE2 = new ServiceBase( 2, "Second Service" );

    protected static ServiceBase[] ALLBASESERVICES =
    {
        //Enumerations list
        SERVICE1,
        SERVICE2
    };
    private static int _maxServiceId = ALLBASESERVICES.Max( s => s.Id );

    //only required if subclassing
    protected static ServiceBase[] combineServices(ServiceBase[] array1, ServiceBase[] array2)
    {
        List<ServiceBase> serviceBases = new List<ServiceBase>();
        serviceBases.AddRange( array1 );
        serviceBases.AddRange( array2 );
        return serviceBases.ToArray();
    }

}

/// <summary>
/// Generic Design for implementing inheritable enum
/// </summary>
public class ServiceJobs : ServiceBase
{
    
    //constructor
    private ServiceJobs(int id, string name)
    : base( id, name )
    {
        _id = id;
        _name = name;
    }

    //only required if subclassing
    protected ServiceJobs(int id, string name, bool isSubClass = true )
    : base( id, name )
    {
        if( id <= _maxServiceId )
            throw new InvalidProgramException("Bad Id in ServiceJobs" );
        _id = id;
        _name = name;
        
    }

    //members
    public override ServiceBase getService(int serviceBaseId)
    {
        if (ALLSERVICES == null)
        {
            ALLSERVICES = combineServices(ALLBASESERVICES, ALLJOBSERVICES);
        }
        return ALLSERVICES.SingleOrDefault(s => s.Id == _id);
    }

    //static methods
    public static ServiceBase getServiceOrDefault(int serviceBaseId)
    {
        return SERVICE3.getService(serviceBaseId);
    }

    //sub class services here
    public static ServiceBase SERVICE3 = new ServiceJobs( 3, "Third Service" );
    public static ServiceBase SERVICE4 = new ServiceJobs( 4, "Forth Service" );
    private static int _maxServiceId = ALLJOBSERVICES.Max( s => s.Id );

    private static ServiceBase[] ALLJOBSERVICES =
    {
        //subclass service list
        SERVICE3,
        SERVICE4
    };

    //all services including superclass items
    private static ServiceBase[] ALLSERVICES = null;

}

请注意,您可以使用枚举而不是整数作为ID,尽管子类需要一个单独的枚举。 枚举类本身可以用各种标志、消息、函数等进行装饰。 通用实现将减少大量代码。

-9

你可以在枚举中执行继承,但是仅限于以下类型。

int、uint、byte、sbyte、short、ushort、long、ulong

例如:

public enum Car:int{
Toyota,
Benz,
}

3
我认为OP是在询问如何从一个枚举类型继承另一个枚举类型,而不仅仅是从基础数字类型继承(在C#中,所有枚举类型都会隐式或显式地继承基础数字类型)。 - reirab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接