在父类中创建可覆盖的枚举



我想创建一个嵌套结构,其中每个类代表一个国家,继承相同的父类Country。每个子类都应该有一个表示不同状态的枚举States

目标是能够选择一个国家,然后选择一个州。

内容将被保存到字典Dictionary<Tuple<string, Type>, object>中,TypeCountryCountry.States

我尝试使用名为Statesenum制作一个interface/abstract class来实现,但这不起作用,因为它是一个类型定义。

有什么解决方法吗?

public abstract class Country
{
public abstract enum States { get; }
}
public class CountryA : Country
{
public new enum States
{
StateA,
StateB,
StateC,
}
}

你的设计是有缺陷的,你需要创建一个带有属性的Country类,例如public string[] States { get; set; }.

然后创建Country类的实例(对象),每个实例(对象)都设置为所需的项States

var usa    = new Country { Name = "USA",    States = new[] { "Alabama", ... } };
var canada = new Country { Name = "Canada", States = new[] { ... } };
// etc

您有几个选择:

你可以在运行时创建一个枚举(见这里:动态创建一个枚举),但我认为这不符合你的需求,因为我想你正在沿着枚举路线前进,以便在编码中易于使用。

你可以实现一个类型安全的枚举模式(参见这里:类型安全的枚举模式),但这更多的编码只是为了能够使用模仿枚举的设计,同时对其余的逻辑进行编码。

我的建议是使用字典并在实例化时从设置文件或外部数据源构建您的"状态"。毕竟,国家及其州/城市/等确实会不时更改名称。将自己锁定在像您所追求的硬编码情况中不会支持这种未来的变化。

祝你好运!

[根据卡米洛-特雷文托的回应编辑]

虽然我当然同意你的设计很可能是有缺陷的,因为你需要数百个类和枚举,但我完全不同意"这是不可能的"的其他答案。

当然可以使用泛型(同时请记住,您不能完全限制为Enum):

public abstract class Country<TStates> 
where TStates: struct, IConvertible, IFormattable, IComparable
{
public abstract TStates[] States { get; }
}
public enum UnitedStatesStates
{
WhoCares, WhoCares2
}
public class UnitedStatesCountry : Country<UnitedStatesStates>
{
public override UnitedStatesStates[] States { get; }
}

现在,我非常怀疑这在(不那么长)的期限内是否有用。

您要求使枚举可继承,如果您不使用枚举,而是使用具有static public个成员的类(可以继承并且每种类型具有不同的成员集),则可以实现这一点。它的行为几乎与枚举一样:

public class Country1
{
public static State State1 { get; } = new State("State 1");
public static State State2 { get; } = new State("State 2");
...
}

应该很清楚Country1.State1是什么,对吧?State可以是更复杂的对象,而不仅仅是一个string。如您所见,它不需要继承,因为国家/地区将州定义为不同的成员。

您可以遵循相同的原则来实现长对象:Planet.Continent.Country.State.Province.Town.Street.Hause.。


你说

内容将保存到字典Dictionary<Tuple<string, Type>, object>中,其中类型将被CountryCountry.States

不要。这些是不同的类型,这是一个糟糕的键选择。如果您需要枚举(查找)状态,则只需将另一个成员添加到Country

public static IEnumerable<State> States
{
get
{
yield return State1;
yield return State2;
...
}
}

然后搜索某些内容可以是一个简单的 linq:

var stateAInCountry1 = ...Countries.OfType<Contry1>().Single().States.Single(o => o.Name == "A");
var countriesWithStateA = ...Countries.Where(o => o.States.Any(o => o.Name == "A"));

不确定通过引入字典来解决什么问题,但是如果您提供了一种轻松迭代的方法,则可以使用适当的键初始化其他数据结构。

我不太清楚,除了编译器提醒您定义这些不同的(!)枚举之外,您是否还想实现其他目标。

实际上,它们一开始没有任何共同点,因此编译器和您都无法从该合约中获得任何优势。

您可以做的是将其声明为

public abstract string[] States {get;}

并从派生类中定义的各个枚举中获取这些字符串。那么常见的情况可能是您希望字符串结果用于信息目的或其他目的。

最新更新