可以像这样使用C#Property

时间:2010-07-27 08:27:57

标签: c# .net

我的其中一位开发人员的代码类似于以下代码段

class Data
{
     public string Prop1
     {
           get
           {
                // return the value stored in the database via a query
           }
           set
           {
                // Save the data to local variable
           }
     }

     public void SaveData()
     {
          // Write all the properties to a file
     }

}

class Program
{
    public void SaveData()
    {
         Data d = new Data();
         // Fetch the information from database and fill the local variable
         d.Prop1 = d.Prop1; 
         d.SaveData();
    }
}

class Data { public string Prop1 { get { // return the value stored in the database via a query } set { // Save the data to local variable } } public void SaveData() { // Write all the properties to a file } } class Program { public void SaveData() { Data d = new Data(); // Fetch the information from database and fill the local variable d.Prop1 = d.Prop1; d.SaveData(); } }

此处Data类属性动态地从DB获取信息。当需要将数据保存到文件时,开发人员创建实例并使用自我赋值填充属性。然后最后调用一个保存。我试图争论财产的使用是不正确的。但他并不相信。

这是他的观点

  1. 有近20个这样的房产。
  2. 除保存外,不需要提取所有信息。
  3. 编写一个实用程序方法来获取all,而不是自我赋值,而不是在属性中使用相同的重复代码。
  4. 这种用法是否正确?

8 个答案:

答案 0 :(得分:17)

我不认为使用相同代码的其他开发人员会很高兴看到:

d.Prop1 = d.Prop1; 

我个人不会这样做。

使用属性从DB加载数据也不是最佳选择。 我会method将数据从DB加载到本地变量,然后您可以使用属性获取该数据。此外,get/set在逻辑上也必须使用相同的数据。使用get从数据库获取数据但使用set处理局部变量很奇怪。

答案 1 :(得分:4)

属性应该尽可能轻量级。

当其他开发人员使用属性时,他们希望它们是对象的内在部分(即已经加载并在内存中)。

这里的真正问题是对称性 - 属性get和set应该相互映射,而它们不会。这与大多数开发人员通常所期望的相反。

不建议从数据库加载属性 - 通常会通过特定方法填充类。

答案 2 :(得分:3)

“正确”通常是旁观者的眼睛。这也取决于您希望您的设计达到多远或多么出色。我永远不会选择你描述的设计,在POCO上进行CRUD操作将成为维护的噩梦。

您的主要问题是缺少 关注点分离 。即,数据对象还负责存储和检索(需要在整个系统中仅定义一次的动作)。因此,您最终会遇到重复,膨胀且无法维护的代码,这些代码很快就会变得非常慢(尝试使用gettor上的连接进行LINQ查询)。

数据库的一个常见场景是使用仅包含属性的小实体类,仅此而已。 DAO层负责使用数据库中的数据检索和填充这些POCO,并仅定义CRUD操作(通过一些泛型)。我建议使用NHibernate进行ORM映射。这里解释的基本原理也适用于其他ORM映射器,并且是explained here

原因,尤其是nr 1,应该是将其重构为更易维护的主要候选者。遇到重复的代码和逻辑时,应该强烈重新考虑。如果上面的gettor真的得到了数据库数据(我希望我误解了),尽快摆脱它。

关注点分离的过度简化示例:

class Data 
{
    public string Prop1 {get; set;}
    public string Prop2 {get; set;}
}

class Dao<T>
{
    SaveEntity<T>(T data)
    {
        // use reflection for saving your properies (this is what any ORM does for you)
    }
    IList<T> GetAll<T>()
    {
        // use reflection to retrieve all data of this type (again, ORM does this for you)
    }
}

// usage:
Dao<Data> myDao = new Dao<Data>();
List<Data> allData = myDao.GetAll();
// modify, query etc using Dao, lazy evaluation and caching is done by the ORM for performance
// but more importantly, this design keeps your code clean, readable and maintainable.

编辑:
你应该问你的同事一个问题:如果你有很多数据(数据库中的行),或者属性是连接查询(外键表)的结果,会发生什么。如果您希望从一种情况(不可维护)平稳过渡到另一种情况(可维护),那么请查看Fluent NHibernate,这很容易被任何人理解。

答案 3 :(得分:3)

这非常糟糕,imo。

  1. 属性应该快速/易于访问;如果在一个房产后面发生了非常沉重的事情,那么它应该是一种方法。
  2. 在同一个房产的吸气器和安装器后面有两个完全不同的东西是非常令人困惑的。 d.Prop1 = d.Prop1 看起来像<无意义的自我分配,而不是“从数据库加载数据”调用。
  3. 即使您必须从数据库中加载20个不同的东西,这样做强制它是20个不同的数据库行程;你确定一次通话中无法获取多个属性吗?在性能方面,这可能会好得多。

答案 4 :(得分:1)

如果我是你,我会写一个序列化/反序列化函数,然后提供属性作为内存结果的轻量包装。

查看ISerialization接口:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx

答案 5 :(得分:1)

这很难处理,

如果您设置Prop1,然后获取Prop1,您可能会得到不同的结果 例如:

//set Prop1 to "abc"
d.Prop1 = "abc";

//if the data source holds "xyz" for Prop1
string myString = d.Prop1;
//myString will equal "xyz"

在没有评论的情况下阅读代码,你会发现mystring等于“abc”而不是“xyz”,这可能会令人困惑。

这将使得处理属性非常困难,并且每次更改属性时都需要保存才能使其工作。

答案 6 :(得分:0)

在我看来,这是一个糟糕的设计。使用属性getter做一些“神奇”的东西会使系统难以维护。如果我加入你的团队,我怎么知道这些属性背后的魔力?

创建一个在行为时调用的单独方法。

答案 7 :(得分:0)

除了同意其他人在此示例中所说的内容之外,如果Data类中还有其他字段会发生什么?即Prop2,Prop3等,每次访问它们时都会返回数据库,以“通过查询返回存储在数据库中的值”。 10个属性将等于10个数据库命中。设置10个属性,10写入数据库。这不会扩大规模。