C# - Code Analysis 2227 Confusion

青春壹個敷衍的年華 提交于 2020-01-13 10:58:10

问题


I have a class property that looks as follows:

public List<Recipe> RecipeList
{
    get { return this._recipeList; }

    set
    {
        this._recipeList = value;
        OnPropertyChanged("RecipeList");
    }
}

In another method I have the following which references the property above.

private void RecipeSearch()
{
            this.RecipeList = RecipeManagerService.SearchByUnit(SearchCriteria)
                               .Where(recipe => recipe.IsApproved == true && !recipe.IsHidden).ToList();
}

Code Analysis is issuing a CA 2227 warning: Change RecipeList to be read-only by removing the setter. Could anyone tell me why?


回答1:


Adding a public setter on a List<T> object is dangerous. You can eliminate this warning by making your setter private:

public List<Recipe> RecipeList
{
    get { return this._recipeList; }

    private set
    {
        this._recipeList = value;
        OnPropertyChanged("RecipeList");
    }
}

This will still allow your class to change this method, but no external source.




回答2:


I think it's suggesting that usually collection properties themselves shouldn't be mutable - it's more common for the collection to be mutable, and just available via a setter.

It's only a suggestion though :)

In this case you'd use:

RecipeList.Clear();
RecipeList.AddRange(RecipeManagerService
                              .SearchByUnit(SearchCriteria)
                              .Where(r => r.IsApproved && !r.IsHidden));

Note that this won't fire the change event though... you might want to use ObservableCollection instead.

This will also mean that anyone can change the contents of the recipe list... do you definitely want that? Another alternative is to expose a ReadOnlyCollection<T> property or something like that, and only make changes within your own class. It really depends what you're trying to do though.




回答3:


Do you want another instance messing with RecipeList? Generally, I don't let anything change my collection instances except the instance that owns the collection. You could make it private.




回答4:


The MSDN description is fairly clear:

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

It wouldn't be good OO if the client of your class could change the list to be a completely different list of Recipes. That is against encapsulation.

Ensuring the clients just add or remove items is what you probably want to do.




回答5:


I don't think there's anything illegal about the code, but it's common practice to have no public setter for collection type properties. Your private RecipeSearch method should just set _recipeList and raise the event, or you could make _recipeList itself a protected property that handles the event.




回答6:


Allowing the list property to be mutated in two ways (via it's own Add and Remove methods and the list instance as a whole) creates an ambiguous interface to those who consume that property. This confuses responsibilities and creates a larger technical debt/maintenance overhead.

Instead, it is often better practise to separate these concerns so that the property provides access to a single instance of the list. If the list instance must be changeable, a separate mechanism for doing so makes it much clearer that the action of interacting with the property and the action of changing which list instance that property points to are distinct.



来源:https://stackoverflow.com/questions/5554566/c-sharp-code-analysis-2227-confusion

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!