【问题标题】:C# Class with Sub-Items带有子项的 C# 类
【发布时间】:2015-01-13 13:51:04
【问题描述】:

假设我想要一个主类,其中包含许多子类,子类都具有相同的属性/方法,并且我需要在许多不同的其他代码部分中访问它们。

示例: 主类:国家

子类/项目:德国、荷兰、大不列颠、法国……

然后为每个国家/地区定义单独的属性,例如人口、单位、...

所以稍后在代码中我可以像访问它一样访问它

if (Country.France.Units < Country.Germany.Units)
Console.WriteLine("foo");

编辑:感谢大家的回答,CodeCaster 的解决方案非常适合我的目的。其他的也是对的,通过字符串值解析字典只是少了一些工作......

【问题讨论】:

  • 看起来有点奇怪的设计 - 您将使用的每个国家/地区的子类。为什么不直接使用var france = new Country() {Name = "France", Units = ...} 之类的东西?
  • 是什么让你认为你需要一个静态类?
  • 您可以从您的每个子类的主类继承,这样 MustInherit 类的属性(在本例中为 Country)成为每个其他类的属性(即法国继承 Country,德国继承国家等)
  • 我同意安迪的观点,只需为每个国家/地区实例化一个主类的新实例。
  • 其实这几乎是一个类实例化的教科书示例。您将有一个国家/地区类,每个特定国家/地区都是该类的一个实例。包括名称是好的(如果需要/需要,您可以覆盖 ToString())并且您可以命名实例,因此您可以先使用 Country France = new Country() 而不是 Country.France.Units,然后您可以只说 if (France.Units &lt; Germany.Units)。跨度>

标签: c# class subitem


【解决方案1】:

您不想这样做,因为对于添加的每个国家/地区,您都必须重新编译,这意味着您无法自动将从外部数据源加载的数据链接到静态类型的属性。

改用字典:

var countries = new Dictionary<string, Country>();

// ...

if (countries["France"].Units < ...)

【讨论】:

    【解决方案2】:

    特别是为了解决当前任务,您可以创建一个 Country 类,其中包含每个国家/地区的私有构造函数和静态属性。

    public class Country
    {
        private Country()
        {
        }
    
        public int Population {get; private set;}
    
        // Static members
    
        public static Country USA {get; private set;}
        public static Country Italy {get; private set;}
    
        static Country()
        {
            USA = new Country { Population = 100000 };
            Italy = new Country { Population = 50000 };
        }
    }
    

    您可以通过以下代码访问它

    Country.USA.Population < Country.Italy.Population
    

    【讨论】:

    • 它不起作用:/它说'成员名称不能与其封闭类型相同'
    • 样例写在原地,我没有验证,所以漏掉了静态构造函数的static关键字。
    • 代码已修复,可以使用
    【解决方案3】:

    你想要的听起来与Color 结构非常相似。它具有大量预定义的类,但仍允许“自定义”颜色。

    然而,与Color 不同的是,Country 的属性可能会随着时间而改变,并且可能受益于拥有可以更新的外部数据源。还有有限数量的国家,因此您可以通过不让数千个“法国”实例四处浮动来优化内存。

    一个适合的模式是Flyweight。您可以通过使用工厂方法最大限度地减少浮动对象的数量,但仍然可以轻松访问一组预定义的国家/地区:

    public class Country
    {
        // properties of a Country:
        public int Population {get; private set;}
        public string Units {get; private set;}
        // etc.
    
        // Factory method/fields follows
    
        // storage of created countries
        private static Dictionary<string, Country> _Countries = new Dictionary<string,Country>();
    
        public static Country GetCountry(string name)
        {
            Country country;
            if(_Countries.TryGetValue(name, out country))
                return country;
            //else
            country = new Country();
            // load data from external source
            _Countries[name] = country;
            return country;
        }
    
        public static Country France { get {return GetCountry("France");} }
        public static Country Germany { get {return GetCountry("Germany");} }
    }
    

    按原样设计的一些注意事项:

    • 它不是线程安全的。您需要添加适当的线程安全性。
    • 国家不是永恒的——如果一个预先定义的国家不复存在,你会怎么做?
    • 理想情况下,工厂将是一个单独的类,因此您可以将Country 类与工厂分离,但我认为Country.France 看起来比CountryFactory.France 更好

    【讨论】:

    • 感谢先生提供这个先进的解决方案,我也在考虑类似于 Color / ConsoleColor 的东西,但不知何故没有提及。
    【解决方案4】:

    如果你不喜欢字典的字符串解析,而且你的列表比较小,你可以这样做:

    List<Country> counties = new List<Country>();
    countries.Add(France as Country);
    countries.Add(Germany as Country);
    ...
    
    var France = countries.FirstOrDefault(t => t is France);
    

    【讨论】:

    • 那不是拳击,那是polymorphism。装箱包装了一个 value 类型。
    • 你说得对,@CodeCaster 我没有意识到它只适用于值类型,我猜我从来没有读过细则
    • 这段代码中FranceGermany的具体类型是什么?为什么要使用as
    • @PieterWitvoet 根据问题,FranceGermanyCountry 类的子类。 as 是一种将对象转换为基本类型的方法
    • 如果它们是子类,则无需使用as。此外,为每个国家/地区创建一个子类可能不是一个好主意 - 为每个国家/地区创建一个 Country 类的实例会更好,假设国家/地区都具有相同的属性(只是具有不同的值)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2019-10-13
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多