C# 为类集合提供健壮的一致性检查

C# 为类集合提供健壮的一致性检查,c#,.net,winforms,C#,.net,Winforms,请给出一些我正在做的工作的背景: 我有一个程序,允许用户修改和创建通用校准。在该校准中包括组。各组所执行的分析类型不同。这些组还包括光谱组,每组只包含一个分子的数据。在这些集合中还包括不同浓度的光谱数据。每个光谱数据是一组离散的数据,由其分辨率(每个点之间的x轴空间)及其光谱范围(x轴范围)指定 建立这些校准文件的一个主要方面是保持每组中所有光谱数据的分辨率和光谱范围一致。这意味着除非光谱数据与其他光谱数据匹配,否则无法添加光谱数据。此外,如果用户删除所有光谱数据,则分辨率和范围将重置,允许将任

请给出一些我正在做的工作的背景:

我有一个程序,允许用户修改和创建通用校准。在该校准中包括组。各组所执行的分析类型不同。这些组还包括光谱组,每组只包含一个分子的数据。在这些集合中还包括不同浓度的光谱数据。每个光谱数据是一组离散的数据,由其分辨率(每个点之间的x轴空间)及其光谱范围(x轴范围)指定

建立这些校准文件的一个主要方面是保持每组中所有光谱数据的分辨率和光谱范围一致。这意味着除非光谱数据与其他光谱数据匹配,否则无法添加光谱数据。此外,如果用户删除所有光谱数据,则分辨率和范围将重置,允许将任何范围或分辨率的光谱数据添加到校准中

问题是:我如何提供一种有效的方法来防止将光谱数据添加到与当前分辨率和光谱范围不匹配的校准中

以下是校准等级的一般说明。这是一个非常笼统的描述,包含了解释我试图做什么所需的唯一信息

class calibration
{
    List<Group> groups;
}


class Group
{
    List<SpectralSet> sets;
}

class SpectralSet
{
    List<SpectraData> spectras;
}

class SpectraData
{
    double firstXPoint;
    double lastXPoint;
    double resolution;
    double[] Ypoints; 
}
类校准
{
列出小组;
}
班级
{
列表集;
}
类谱集
{
列出思百吉;
}
频谱类
{
双第一点;
双末梢点;
双分辨率;
双[]分;
}

我相信您可以应用各种各样的奇特设计模式来实施您提到的规则

然而,为了简单起见,我只想用一个
AddGroup
方法将逻辑封装在
calibration
类中,该方法验证添加的
group
是否符合校准的要求。类似地,我将为
类创建一个
AddSpectralSet
方法,作为
集合中的守门员

此时,根据这些内容的更改频率,我会考虑将
集合和
集合公开为
ReadOnlyCollection
,以确保代码不会在不使用指定方法的情况下尝试添加项


希望这能有所帮助。

您的方法可能会有所不同,但这里概述了如何实现这一点。您需要执行以下操作:

  • 仅公开不可变的公共集合属性以及
    Add
    方法,以便您自己进行验证
例如,您不想执行以下操作:

class Group
{
    public List<SpectralSet> sets;
}
  • 存储数据必须匹配的条件
我不太确定光谱范围是什么,所以我将以分辨率为例。您可以简单地将其扩展到任何范围标准。至少有三种可能的方法可以做到这一点:

  • 构造类时,将构造函数中允许的解析传递给它,并使其不可变
  • 添加和删除时,根据需要更新允许的分辨率
  • 不要显式存储分辨率,每次添加或删除时都要计算分辨率
  • 其中,选项1是最简单的。当你能使事物尽可能地不变时,生活总是容易得多。所以你会做一些类似的事情:

    class Group
    {
        private List<SpectralSet> _sets;
        public IEnumerable<SpectralSet> Sets { get { return _sets; } }
        public readonly double Resolution;
    
        public Group(double resolution)
        {
            Resolution = resolution;
        }
    
        public void Add(SpectralSet set)
        {
            if(set.Resolution != resolution)
                //Throw an Exception here, or however you want to handle invalid data
            _sets.Add(set);
        }
    
        //Have a similar Remove method
    }
    
    类组
    {
    私有列表集;
    公共IEnumerable集合{get{return\u集合;}}
    公共只读双分辨率;
    公共组(双分辨率)
    {
    分辨率=分辨率;
    }
    公共无效添加(频谱集集)
    {
    if(set.Resolution!=分辨率)
    //在此处引发异常,或者以您希望的方式处理无效数据
    _集合。添加(集合);
    }
    //有类似的删除方法
    }
    
    在本例之后,您包含的每个类都需要一个具有相同逻辑类型的
    分辨率
    参数,只需检查您试图添加的任何直接子类的
    分辨率
    。同样地,无论你使用什么光谱范围

    如果清除了所有数据,您还希望能够更改允许的分辨率。最简单的方法是在清除数据时创建新对象,而不仅仅是清除现有对象中的集合

    • 使
      SpectraData
      不可变

    如果您可以从一个精心选通的集合中获取一个
    SpectraData
    ,并任意更改它,那么所有这些都是无用的。使任何需要验证的内容都不可变,只允许在构建时设置它。如果您有不这样做的要求,您需要非常仔细地考虑如何允许它被更改。

    问题是什么?请检查我所做的编辑。@Berigan,是什么阻止您(或您的代码)检查SpectraData是否符合您所说的标准(If语句?),如果满足标准,则仅将其添加到SpectraData.spectras…?2个问题:1。就
    SpectraData
    的属性而言,“光谱范围”到底是什么。哪些
    SpectraData
    需要匹配?所有的
    SpectraData
    都在一个集合中吗?或者单个
    组中所有
    频谱集中的所有
    频谱数据
    ?或者所有
    spectraldata
    在所有
    spectraldset
    s中跨越所有
    s?在问题I中指定范围为x轴范围。最高x值和最低x值定义了此上下文中的范围。添加到任何组中任何集合的任何spectradata必须与任何集合中任何组中已存在的spectradata相匹配。添加到任何组的任何集合中的第一个spectradata几乎定义了接下来添加的任何spectradata的格式要求。此外,如果最后一个光谱数据被删除,那么当然,光谱要求
    class Group
    {
        private List<SpectralSet> _sets;
        public IEnumerable<SpectralSet> Sets { get { return _sets; } }
        public readonly double Resolution;
    
        public Group(double resolution)
        {
            Resolution = resolution;
        }
    
        public void Add(SpectralSet set)
        {
            if(set.Resolution != resolution)
                //Throw an Exception here, or however you want to handle invalid data
            _sets.Add(set);
        }
    
        //Have a similar Remove method
    }