【问题标题】:What to pass? Reference Object or Value Type?要通过什么?引用对象还是值类型?
【发布时间】:2010-02-15 18:37:51
【问题描述】:

伙计们,我有一个“最佳实践问题”例如我有这个课程:

class Person
{
   public int age {get; set;}
}

class Computer
{
   public void checkAge(Person p)  // Which one is recommended   THIS
   {
       // Do smthg with the AGE
   }

   public void checkAge(int p)     // OR THIS
   {
       //Do smthg with the age.
   }
}

建议通过什么?正是我需要的(int-value 类型)或整个对象(引用类型)

我问这个是因为我在我正在制作的应用程序上使用 LINQ,并且我创建了许多我应该传递 ID(外键)的实体,但我传递了对象。

最好的方法是什么?

【问题讨论】:

  • +1 我一直有这种困惑,不知何故被遗忘了,现在已经澄清了。谢谢。
  • 这是我一直有疑问的问题。我需要问:D

标签: c# oop


【解决方案1】:

函数checkAge 应该只接收执行其工作所需的最少信息量。添加任何其他内容只会创建人为的依赖关系。如果只需要int,那么这就是我应该采取的解决方案。

【讨论】:

  • 优秀的 Jared,所以我应该记住提供所需的最少信息。- 有时我需要传递 2 个整数,然后我应该给函数 2 个整数等等,对吗?
  • @MRFerocious,我会创建 2 个函数。只需要 1 个 int 的版本和另一个接受 2 个 ints 并且具有明显不同的行为的版本
  • 这个原理被称为得墨忒耳定律:en.wikipedia.org/wiki/Law_of_Demeter
【解决方案2】:

我认为在这种情况下,答案可能都不是。要么“年龄”被分解到它自己的类中,要么如果操作是特定于 Person 的上下文,它会在 Person 类本身中找到。

【讨论】:

    【解决方案3】:

    根据给出的信息,这两种解决方案都不好

    第一个解决方案要求 Computer 类知道 Person.Age,原因不明

    第二个方法给Computer类附加了一个与Computer对象的属性无关的方法

    一些上下文会有所帮助 - 如果这是一个验证,那么 CheckAge 属于 Person 类(可能具有 IsAgeAcceptable 属性)

    为什么计算机要检查一个人的年龄?这个问题的答案决定了什么是有意义的......

    【讨论】:

    • @Steven A. Lowe - 我认为 OP 只是举个例子。我确定或希望他在 Computer 类中没有真正的 checkAge 函数。
    • 哈哈哈伙计们,当然这只是一个例子。我问这个是因为我使用 Linq 并且我需要传递一些 id,但在某些情况下我有 3 个,所以我决定传递对象。-所以我将只传递整数。
    【解决方案4】:

    函数遵循得墨忒耳定律。基本上,法律规定实体应该松散耦合。问自己以下问题,计算机对象是否应该知道人对象?在这种情况下,也许你在 checkAge 中所做的只是检查一个 int 值。如果是这种情况,那么是什么让您认为需要传递整个对象?在这种情况下,只需传递人员年龄并将其作为 int 输入。

    所以更喜欢

    public void checkAge(int n)
    

    【讨论】:

      【解决方案5】:

      我想指出的是,在传递引用时,引用是一个 32 位整数,而数据类型是被复制的。因此,如果您的值类型大于 32 位 int,如果性能或内存有任何问题,请通过引用传递。

      【讨论】:

        【解决方案6】:

        我要指出int Age 可能不是存储该值的最佳方式。 (Why is DateTime a Property and not a Method )

        class Person : IBorn
        {
          public DateTime Birth {get; set;}
        }
        
        interface IBorn
        {
          DateTime Birth {get; set;} 
        }
        
        interface IDateTimeFactory
        {
          DateTime Now();     
        }
        
        class DefaultDateTimeFactory : IDateTimeFactory
        {
          public DateTime Now()
          {
            return DateTime.Now;
          }
        }
        
        public static class IBornExtensions
        {
          public TimeSpan AgeFromNow(this IBorn birthed, IDateTimeFactory dtf)
          {
            return dtf.Now() - birthed.Birth;
          }
          public TimeSpan AgeFrom(this IBorn birthed, DateTime from)
          {
            return from - birthed.Birth;
          }
        }
        
        class Computer
        {
          public void checkAge(IBorn birthed)        
          {
            var age = birthed.Age((new DefaultDateTimeFactory()).Now());
          }
        }
        

        我敢肯定有人在想,“这个答案有很多代码,肯定看起来很离谱”。就像DateTime.Now 应该是一个方法一样(因为方法返回的值可能会在每次调用时更改,并且属性通常不应更改每次调用的值,请参阅上面的链接),每次调用的年龄更改,所以属性可能应该是 Birth。接下来我将确定 Age 的方法封装为 Extension 方法,因为任何可以是 IBorn 的东西肯定都可以有一个 Age(忽略某个东西已经死了的哲学问题,它是否有一个 Age :P)。最后,创建了IDateTimeFactory 对象,这样人们就可以对 Age 方法进行单元测试以确定它是否正确计算年龄(否则,硬编码DateTime.Now 意味着您无法分辨出某事物与其他事物相比的年龄,例如 old is my哥哥和姐姐相比)。

        【讨论】:

          猜你喜欢
          • 2013-07-14
          • 1970-01-01
          • 1970-01-01
          • 2010-11-25
          • 2010-12-04
          • 1970-01-01
          • 1970-01-01
          • 2012-10-11
          • 2013-01-11
          相关资源
          最近更新 更多