2011-04-05 64 views
5

我有一个类属性,如下所示:C# - 代码分析2227困惑

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

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

在另一种方法我有引用上面的属性如下。

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

代码分析发出CA 2227警告:通过删除setter将更改RecipeList为只读。有谁能告诉我为什么?

+0

是否有任何东西使用setter? – Douglas 2011-04-05 15:45:49

+0

@Douglas - 是的,我有XAML绑定它。 – Hosea146 2011-04-05 15:46:42

回答

3

List<T>对象上添加公共setter是很危险的。您可以通过您的二传手私人消除这样的警告:

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

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

这仍然可以让你的类来更改这个方法,但是没有外部来源。

+0

谢谢。这正是我应该做的。 – Hosea146 2011-04-05 15:51:21

1

你想要另一个实例与RecipeList搞混吗?通常,我不会让任何东西改变我的集合实例,除了拥有集合的实例。你可以制作它private

2

我认为这是暗示通常集合属性本身不应该是可变的 - 集合是可变的,并且通过setter可用。

这只是一个建议,但:)

在这种情况下,你会使用:

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

注意这不会火更改事件虽然...你可能想改用ObservableCollection。

这也意味着任何人可以改变配方列表的内容......你一定要这样吗?另一种选择是公开一个ReadOnlyCollection<T>属性或类似的东西,只在你自己的类中进行更改。这真的取决于你想要做什么。

0

我不认为代码有任何不合法的地方,但是对于集合类型属性没有公共setter是常见的做法。您的私人RecipeSearch方法应该只设置_recipeList并引发该事件,或者您可以让_recipeList本身成为处理事件的受保护属性。

1

MSDN description是相当清楚的:

可写的集合属性允许 用户与 更换收集了完全不同的集合

它不会是好的OO如果客户端你的班级可以将列表更改为完全不同的食谱列表。这是针对encapsulation

确保客户只需添加或删除项目是您可能想要做的。

0

允许列表属性以两种方式进行变异(通过它自己的AddRemove方法和列表实例作为一个整体)为使用该属性的人员创建了一个模糊的接口。这混淆了责任,造成了更大的技术债务/维护费用。

相反,将这些问题分开以便该属性可以访问列表的单个实例通常是更好的做法。如果列表实例必须是可更改的,那么一个单独的机制可以更清楚地表明与属性交互的操作以及更改属性指向的不同列表实例的操作。