CA2227 的解决方案或更好的方法? [英] Solution for CA2227 or better approach?

查看:29
本文介绍了CA2227 的解决方案或更好的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仅使用代码分析来清理、组织和确保针对特定警告的所有实例全局执行这些更改.我进入决赛了,它是 CA2227.

I'm only using Code Analysis for cleaning, organizing and ensuring these changes are globally performed for all instances of a particular warning. I'm down to the final, and it's CA2227.

CA2227 集合属性应该是只读的 将 '' 更改为通过删除属性设置器实现只读.

CA2227 Collection properties should be read only Change '' to be read-only by removing the property setter.

请注意,这是用于 EDI 文档的映射.这些类将代表整个或部分 EDI 文档.

public class PO1Loop
{

    public SegmentTypes.PO1LoopSegmentTypes.PO1 PO1 { get; set; }

    public Collection<SegmentTypes.PO1LoopSegmentTypes.PID1> PIDRepeat1 { get; set; }

    public Collection<SegmentTypes.PO1LoopSegmentTypes.PID2> PIDRepeat2 { get; set; }

    public SegmentTypes.PO1LoopSegmentTypes.PO4 PO4 { get; set; }

    /* Max Use: 8 */
    public Collection<SegmentTypes.PO1LoopSegmentTypes.ACK> ACKRepeat { get; set; }

}

你可以看到所有的 Collection 属性都会给我这个警告,而且有数百个.使用上面的类时,我在没有任何数据的情况下实例化它.然后在外部添加数据并通过其公共访问器设置每个单独的变量.我没有使用构造函数方法准备和传递所有数据来实例化这个类(IMO 对于这些可以达到的大小很容易对眼睛造成严重破坏).完成并分配所有属性后,该类将作为一个整体用于生成它所代表的文档部分.

You can see all of the Collection properties will give me this warning, and there are hundreds of them. When using the above class I instantiate it without any data. Then externally I add the data and set each individual variable through its public accessor. I do not instantiate this class with all the data prepared and passed using a constructor method (IMO for the size these can reach it can easily wreak havoc on the eyes). When complete and all properties are assigned the class as a whole is then used to generate that part of a document it represents.

我的问题是,对于上述用法,正确设置它的更好方法是什么?我是否保留公共访问器并完全抑制此警告,还是有完全不同的解决方案可行?

My question is, for the usage described above, what would be a better approach for setting this up correctly? Do I keep the public accessors and suppress this warning entirely, or is there a entirely different solution that would work?

推荐答案

MSDN 说明了该错误,以及如何避免它.

Here's what MSDN says about the error, and also how you can avoid it.

这是我对这个问题的看法.

Here's my take on the issue.

考虑以下类:

class BigDataClass
{
    public List<string> Data { get; set; }
}

这个类会抛出完全相同的问题.为什么?因为Collections不需要需要一个setter.现在,我们可以对该对象做任何事情:将 Data 分配给任意 List,向 Data 添加元素code>,从Data 中删除元素,等等.如果我们删除setter,我们只会失去直接分配给它的能力财产.

This class will throw that exact same issue. Why? Because Collections do not need a setter. Now, we can do anything with that object: assign Data to an arbitrary List<string>, add elements to Data, remove elements from Data, etc. If we remove the setter, we only lose the ability to directly assign to that property.

考虑以下代码:

class BigDataClass
{
    private List<string> data = new List<string>();
    public List<string> Data { get { return data; } } // note, we removed the setter
}

var bigData = new BigDataClass();
bigData.Data.Add("Some String");

此代码完全有效,实际上是推荐的操作方式.为什么?因为 List 是对包含剩余数据的内存位置的引用.

This code is perfectly valid and in fact the recommended way to do things. Why? Because the List<string> is a reference to a memory location, that contains the remainder of the data.

现在,唯一你现在不能用它做的事情是直接设置Data 属性.IE.以下无效:

Now, the only thing you cannot now do with this, is directly set the Data property. I.e. the following is invalid:

var bigData = new BigDataClass();
bigData.Data = new List<string>();

不一定是件坏事.您会注意到在许多 .NET 类型上使用了此模型.这是不变性的基础.您通常不希望直接访问Collections的可变性,因为这会导致一些意外行为,从而产生奇怪的问题.这就是 Microsoft 建议您省略 setter 的原因.

This is not necessarily a bad thing. You'll notice that on many .NET types this model is used. It's the basics of immutability. You usually do not want direct access to the mutability of Collections, as this can cause some accidental behavior that has strange issues. This is why Microsoft recommends you omit setters.

示例:

var bigData = new BigDataClass();
bigData.Data.Add("Some String");
var l2 = new List<string>();
l2.Add("String 1");
l2.Add("String 2");
bigData.Data = l2;
Console.WriteLine(bigData.Data[0]);

我们可能期待 Some String,但我们会得到 String 1.这也意味着您无法可靠地将事件附加到相关Collection,因此您无法可靠地确定是添加了新值还是删除了值.

We might be expecting Some String, but we'll get String 1. This also means that you cannot reliably attach events to the Collection in question, so you cannot reliably determine if new values are added or values are removed.

可写集合属性允许用户用完全不同的集合替换集合.

A writable collection property allows a user to replace the collection with a completely different collection.

本质上,如果您只永远需要运行一次构造函数或赋值,则省略 set 修饰符.您不需要它,直接分配集合是违反最佳实践的.

Essentially, if you only ever need to run the constructor, or assignment, once, then omit the set modifier. You won't need it, direct assignment of collections is against best-practices.

现在,我不是说永远不要在 Collection 上使用 setter,有时您可能需要一个,但通常不应该使用它们.

Now, I'm not saying never use a setter on a Collection, sometimes you may need one, but in general you should not use them.

你总是可以在Collections上使用.AddRange.Clone等,你只会直接赋值的能力.

You can always use .AddRange, .Clone, etc. on the Collections, you only lose the ability of direct assignment.

最后,如果我们希望 SerializeDeserialize 包含我们的 Collection 而没有 set?好吧,总是有不止一种方法可以做到,最简单的(在我看来)是创建一个表示序列化集合的 property.

Lastly, what do we do if we wish to Serialize or Deserialize a class that contains our Collection without a set? Well, there is always more than one way to do it, the simplest (in my opinion) is to create a property that represents the serialized collection.

以我们的 BigDataClass 为例.如果我们希望使用以下代码Serialize,然后Deserialize这个类,Data 属性将没有元素.

Take our BigDataClass for example. If we wished to Serialize, and then Deserialize this class with the following code, the Data property would have no elements.

JavaScriptSerializer jss = new JavaScriptSerializer();
BigDataClass bdc = new BigDataClass();
bdc.Data.Add("Test String");
string serd = jss.Serialize(bdc);
Console.WriteLine(serd);
BigDataClass bdc2 = jss.Deserialize<BigDataClass>(serd);

所以,为了解决这个问题,我们可以简单地修改一下我们的 BigDataClass,让它使用一个新的 string 属性来实现 Serialization 的目的.

So, to fix this, we can simply modify our BigDataClass a bit to make it use a new string property for Serialization purposes.

public class BigDataClass
{
    private List<string> data = new List<string>();
    [ScriptIgnore]
    public List<string> Data { get { return data; } } // note, we removed the setter

    public string SerializedData { get { JavaScriptSerializer jss = new JavaScriptSerializer(); return jss.Serialize(data); } set { JavaScriptSerializer jss = new JavaScriptSerializer(); data = jss.Deserialize<List<string>>(value); } }
}

另一个选项始终是 DataContractSerializer(一般来说,这确实是一个更好的选择.)您可以在 这个 StackOverflow 问题.

Another option is always the DataContractSerializer (which is really a better option, in general.) You can find information about it on this StackOverflow question.

这篇关于CA2227 的解决方案或更好的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆