如何在 C# 中使用强制结构和无行为对相关不变数据进行分组

     2023-02-18     245

关键词:

【中文标题】如何在 C# 中使用强制结构和无行为对相关不变数据进行分组【英文标题】:How to Group Related Unchanging Data with Enforced Structure and No Behavior in C# 【发布时间】:2021-12-28 20:09:41 【问题描述】:

我正在用 C# 构建一个 winforms 应用程序,该应用程序与产品交互以读取和写入 EEPROM 寄存器。该产品有多个不同版本,每个版本都对相同范围的 EEPROM 寄存器有独特的用途。 GUI 必须了解每种产品类型的每个寄存器的功能。因此,我需要为每种产品类型存储一个唯一的字典,将 EEPROM 寄存器地址与有关该寄存器如何用于该给定产品类型的数据相关联,我将其称为RegisterDictionary。除了这个RegisterDictionary,还有一些其他产品特定数据SpecificData 以及产品之间的共享数据SharedData,我也必须存储这些数据。 RegisterDictionarySpecificDataSharedData 的值对于给定的产品类型永远不会改变,但将来可能会添加新的产品类型。

我想知道对所有这些数据(类或结构)进行分组的最佳做法是什么,并且我想知道如何在不同产品类型(抽象类或接口)的数据组之间实施一致的结构.我看到的三个解决方案如下:

// Option 1: create static classes for each product type
// Advantage: I don't have to instantiate an object to access data
// Disadvantage: I have no way to enforce the structure of a static class.
// Disadvantage: No inheritance means SharedData must be repeated in each class.
// Potential Disadvantage: I am declaring a class with only unchanging properties and no real
// methods. Is this isolation of data without behavior hostile to object oriented design philosophy?

public static class ProductTypeA

    public static readonly Dictionary<string, string> RegisterDictionary get;

    public static readonly int SpecificData get;

    public static readonly int SharedData get;


public static class ProductTypeB

    public static readonly Dictionary<string, string> RegisterDictionary get;

    public static readonly int SpecificData get;

    public static readonly int SharedData get;

///////////////////////////////////////////////////////////////////////////////////////////////
// Option 2: Create an abstract parent class to enforce consistent ProductTypeX class structure
// Advantage: ProductType derived classes have an enforced structure.
// Advantage: Inheritance from parent means SharedData can be shared by derived classes.
// Disadvantage: I do have to create a ProductTypeX instance to access this data
// Potential Disadvantage: I am declaring a class with only unchanging properties and no real
// methods. Is this isolation of data without behavior hostile to object oriented design philosophy?

public abstract class ProductType


    public abstract Dictionary<string, string> RegisterDictionary get;

    public abstract int SpecificData get;

    public int SharedData get; = 1; //non-abstract to share among derived classes


public class ProductTypeA : ProductType // Only one ProductTypeX class shown for brevity

    public override Dictionary<string, string> RegisterDictionary get;

    public override int SpecificData get;


//////////////////////////////////////////////////////////////////////////////////////////////
// Option 3: Create a struct that implements an interface to enforce consistent ProductTypeX struct structure
// Advantage: ProductTypeX structs that implement IProductType have an enforced structure.
// Advantage: Default implementation from IProductTpe means SharedData can be shared by structs
// that implement this interface
// Potential Advantage: Structs may be more suited to group data with no behavior?
// Disadvantage: I do have to create a ProductTypeX instance to access this data

public interface IProductType


    Dictionary<string, string> RegisterDictionary get;

    int SpecificData get;

    int SharedData // This is my default implementation of SharedData
    
         get => 1;
     


public struct ProductTypeA : IProductType // Only one ProductTypeX struct shown for brevity

    public Dictionary<string, string> RegisterDictionary get;

    public int SpecificData get;


上述实现中的任何一个都比其他实现更好吗?

为了澄清,我的主要困惑围绕以下几点:

对我来说,必须实例化一个类或结构以仅访问它并不完全有意义 独立于实例本身且仅依赖于实例类型的数据。 这就是我考虑使用静态类选项的原因。如果数据存储在静态类中 不必通过一个实例来访问它 1. 对我来说(稍微)更多的工作,并且 2. 似乎它会误导读者认为数据取决于实例而不是 比类型。

存储相关不变的数据是否一定是反面向对象的思想? 类或结构中的行为(方法)?我试图这样做的事实是否表明我 是否已经分离了应该耦合在自己的类中的数据和行为?

如果以上都不是,那么将不变的数据存储在类或结构中哪个更好?在 微软的结构文档,他们说“通常,你使用结构类型来设计 提供很少或不提供行为的以数据为中心的小型类型”。这几乎回答了这个问题, 但没有解决我的结构或类将完全不变的事实;回到 第一点,结构要求我创建一个实例来访问 数据,即使数据不依赖于它绑定到类型的实例。

【问题讨论】:

【参考方案1】:

在类或结构中存储没有行为(方法)的相关不变数据是否一定是反面向对象的思想?

使用静态类来保存常量数据很好,这是 C# 中存在此功能的原因之一。但是,任何访问以这种方式声明的产品类型的代码都不可重用。如果您有一个访问ProductTypeA.SpecificData 的显示方法,那么该方法永远不能用于显示不同类型的产品。

方法二和三基本相同。这绝对是一种更好的方法,因为您可以编写接受基本 ProductType 的代码,而不是将您的方法耦合到一种特定类型。我看到这种方法的主要问题是您还定义了只能用作单例的类。例如。你永远不会创建ProductTypeA 的两个实例。在面向对象编程中,类用于定义特定类型的所有对象的属性和行为。如果该类的每个实例都具有完全相同的属性值和完全相同的行为,那么就不需要类。

为什么不简单地创建一个ProductType 类,并创建该类的多个实例?

public class ProductType

    public IReadOnlyDictionary<string, string> RegisterDictionary  get; 

    public int SpecificData  get; 

    public int SharedData  get; 

    public ProductType(IReadOnlyDictionary<string, string> registerDictionary, int specificData, int sharedData = 1)
    
        RegisterDictionary = registerDictionary;
        SpecificData = specificData;
        SharedData = sharedData;
    

像这样实例化类还可以让您选择将配置存储在 json 文件中,如果您添加更多产品类型,则无需重新编译应用程序

【讨论】:

您好,感谢您的周到回复。我认为您正在解决我关于单例想法的问题的核心。我喜欢您的“只使用 ProductType 类”的想法,我唯一担心的是我需要从多个类中访问 ProductType 实例。我想我可以创建一个静态工厂类,将相关数据传递给构造函数,然后用公共静态属性包装创建的实例。你支持那个方法还是你会用另一种方法?另外,如果我不能使用 JSON 文件,你建议如何存储特定的 ProductType 数据来创建实例? 是的,工厂是允许其他类访问您的产品类型而无需关心数据来自何处的好方法。在一个大项目中,我建议您使用依赖注入来为每个服务提供工厂。在 WinForms 应用程序中,让依赖注入工作可能会很痛苦,因此工厂的静态实例就足够了。 您绝对可以在 WinForm 应用程序中包含一个 json 文件。如果由于其他原因您不能使用 json 文件,我认为这意味着您不能使用任何类型的基于文本的文件。代码内解决方案是创建和初始化名为 ProductTypeAProductTypeB 等的 ProductType 类的静态只读实例。

在哪里“定位” C# 结构? / 如何在项目中组织结构

】在哪里“定位”C#结构?/如何在项目中组织结构【英文标题】:Whereto\'locate\'C#structs?/howtoorganizestructswithinaproject【发布时间】:2011-09-1922:48:12【问题描述】:我试图了解在项目中放置C#和/或C++结构的约定。在它自己的源文件中... 查看详情

如何使用 C# Firebird 对数据库执行选择查询并将其显示在 shell 中?

】如何使用C#Firebird对数据库执行选择查询并将其显示在shell中?【英文标题】:HowtoexecuteaselectqueryondatabaseusingC#Firebirdanddisplayitinshell?【发布时间】:2021-12-0110:45:31【问题描述】:我刚开始在VisualStudio中学习C#,我有一个任务要做... 查看详情

如何在 C# 中使用结构数组

】如何在C#中使用结构数组【英文标题】:HowuseStructArrayinC#【发布时间】:2016-04-2209:11:48【问题描述】:我是C#新用户。我在下面有一个C/C++结构:typedefstructfloatx;floaty;Point2f;typedefstructintid;unsignedcharcharcode;CharResultInfo;typedefstructintst... 查看详情

C# 联合结构编组

...ioctl:SetFormat和GetFormat;虽然前者运行良好(就像我实际使用的其他十几个一样),但后者给我带来了糟糕的记忆行为。GetForm 查看详情

c#如何将结构的引用添加到数组或列表?

】c#如何将结构的引用添加到数组或列表?【英文标题】:c#howtoaddareferenceforastructtoanarrayorlist?【发布时间】:2018-04-0306:51:41【问题描述】:C#和面向对象的新手我正在创建结构中保存的预定义数据(不会改变)。我想在数组或列... 查看详情

DDD - 如何对跨聚合的集合强制执行不变量

】DDD-如何对跨聚合的集合强制执行不变量【英文标题】:DDD-Howtoenforceinvariantsoncollectionsacrossaggregates【发布时间】:2020-06-0805:04:47【问题描述】:假设我们销售汽车,定制汽车。客户选择CarModel,然后开始配置CarModel。在我们店里... 查看详情

如何在 powershell 中添加和使用 c# 结构

】如何在powershell中添加和使用c#结构【英文标题】:Howtoaddanduseac#structinpowershell【发布时间】:2021-11-1012:47:53【问题描述】:我正在尝试将POINT结构添加到powershell以在winapiGetCursorPos函数中使用。这是我尝试过的:$MethodDefinition=@\'[... 查看详情

C# 中修饰符的基础结构和行为

...的行为。所以它们的行为类似于属性。但是它们在内部是如何工作的呢?他们是否从.Net类库中调用任何代码或任何属性?【问题讨论】:不确定我是否理解这个问题??你想知道它们是做什么的,或 查看详情

如何使用多线程处理缓存的数据结构(例如 openmp)

】如何使用多线程处理缓存的数据结构(例如openmp)【英文标题】:howtohandlecacheddatastructureswithmulti-threading(e.g.openmp)【发布时间】:2015-01-1600:58:34【问题描述】:我正在使用OpenMP来并行化我们的C++库。在那里,我们有很多地方可... 查看详情

如何在 C# 中按 ID 对 JSON 数据进行分组

】如何在C#中按ID对JSON数据进行分组【英文标题】:HowtogroupJSONdatabyIDinC#【发布时间】:2021-11-1708:40:51【问题描述】:将数据表中的数据序列化后获取这种格式的JSON这是读取excel文件并将数据存储在数据表中后的结果。后来使用ne... 查看详情

如何在 React 中强制渲染组件

】如何在React中强制渲染组件【英文标题】:HowtoforcecomponentrenderinReact【发布时间】:2021-03-0514:27:16【问题描述】:我正在对API进行简单的ajax调用,该API每5秒生成一次数据,使用observables正确接收数据,并且数据状态按预期更新... 查看详情

如何在 C# 中立即强制显示器进入省电模式?

】如何在C#中立即强制显示器进入省电模式?【英文标题】:HowcanIforcethemonitorintopowersavingmodeimmediatelyinC#?【发布时间】:2016-06-2223:35:51【问题描述】:我有两台显示器(HPEliteDisplayE190i),都连接到两台计算机(2xVGA+DP)。这些显示器还... 查看详情

如何在 C# 中复制 Python 的 sorted 内置函数的行为?

】如何在C#中复制Python的sorted内置函数的行为?【英文标题】:HowcanIreplicatethebehaviorofPython\'ssortedbuilt-infunctioninC#?【发布时间】:2014-01-3001:21:22【问题描述】:我有一个Python字典列表。此列表在Web服务之间作为json传递。这些Web服... 查看详情

如何在 Java 中获取 Group.Captures(来自 C# 中的 RegEx)的行为?

】如何在Java中获取Group.Captures(来自C#中的RegEx)的行为?【英文标题】:HowtogetbehaviorofGroup.Captures(fromRegExinC#)inJava?【发布时间】:2012-02-2202:05:03【问题描述】:我正在寻找的是在Java的正则表达式API中以最易于使用的方式模仿C#... 查看详情

如何使用 ef 对迁移构建强制执行 Restrict DeleteBehavior?

】如何使用ef对迁移构建强制执行RestrictDeleteBehavior?【英文标题】:HowtoenforceRestrictDeleteBehaviorformigrationbuildusingef?【发布时间】:2018-07-2622:18:16【问题描述】:我有一个相关的PatientRegistry表,它有三个相关的表,它们具有one-to-man... 查看详情

如何在 C# 中强制执行方法的顺序

】如何在C#中强制执行方法的顺序【英文标题】:Howtoenforcemethodexecutionorderinc#【发布时间】:2021-08-1308:38:39【问题描述】:长话短说,我有以下课程:publicclassFlowBasePipeline<T>privateList<StepBaseBusiness<T>>stepList=newList<Ste... 查看详情

如何在c#中使用xelement获取xml节点值

】如何在c#中使用xelement获取xml节点值【英文标题】:Howtogetxmlnodevaluebyusingxelementinc#【发布时间】:2021-05-1406:15:20【问题描述】:我有一个如下所示的XML,我想在其中读取一个名为1526726702的节点。因此,这个特定的节点集合sn-p,... 查看详情

如何在 C# 中使用 Random 类对数组进行洗牌 [重复]

】如何在C#中使用Random类对数组进行洗牌[重复]【英文标题】:HowtouseRandomclasstoshufflearrayinC#[duplicate]【发布时间】:2021-11-2821:02:45【问题描述】:每个人。所以我今天想练习C#,但我一直在想如何使用Random类来简单地打乱数组例如... 查看详情