【问题标题】:Why private field of the class are visible when passing same type as a parameter of method C#?为什么当传递相同类型作为方法 C# 的参数时,类的私有字段是可见的?
【发布时间】:2012-05-25 13:42:04
【问题描述】:

让我们看看这堂课:

    public class Cluster
    {
        private List<Point> points; //private field

        public float ComputeDistanceToOtherClusterCLINK(Cluster cluster)
        {
            var max = 0f;
            foreach (var point in cluster.points) // here points field are accessible
            {
                  .......
            }
            return max;
        }
    }

为什么我可以访问私有字段?

我可以使用此功能还是可能是不好的做法?

【问题讨论】:

  • 这是设计使然,对静态“工厂方法”和“克隆”方法特别有用。
  • 可以在类型内部访问私有字段。 ComputeDistanceToOtherClusterCLINK 是同一个类的成员。所以应该可以从方法体中访问私有字段。

标签: c# private-members


【解决方案1】:

为什么我可以访问私有字段?

因为您在定义私有字段的同一个类中。

【讨论】:

    【解决方案2】:

    如有疑问,请检查语言规范。

    根据 C# 语言规范,第 3.5.1 节:

    3.5.1 声明的可访问性

    成员声明的可访问性可以是以下之一:

    • Public,通过在成员声明中包含 public 修饰符来选择。 public 的直观含义是“访问不受限制”。
    • 受保护,通过在成员声明中包含受保护的修饰符来选择。 protected 的直观含义是“仅限于包含类或从包含类派生的类型的访问”。 -Internal,通过在成员声明中包含 internal 修饰符来选择。 internal 的直观含义是“仅限此程序访问”。
    • 受保护的内部(意味着受保护的或内部的),通过在成员声明中包括受保护的和内部的修饰符来选择。 protected internal 的直观含义是“访问仅限于此程序或从包含类派生的类型”。
    • Private,通过在成员声明中包含 private 修饰符来选择。 private 的直观含义是“仅限于包含类型的访问”。

    从上一节可以看出,包含类的所有方法(在你的例子中是Cluster)都可以访问私有字段points。

    ...不,这根本不是一个坏习惯:这正是私有字段的目的!

    【讨论】:

      【解决方案3】:

      Private 表示类范围的私有。令人惊讶的是,您甚至可以访问同一类的另一个对象的私有字段。

      public class A
      {
          private int _i;
      
          public bool AreEqual(A otherObject)
          {
              return this._i == otherObject._i;
          }
      }
      

      OOP(面向对象编程)的主要方面之一是封装。这意味着一个对象禁止直接访问私有数据(字段)。相反,它提供了公共方法(包括属性 getter 和 setter)来操作和访问其数据。但这也意味着这些方法必须能够访问这些私有字段,否则私有字段将毫无意义。


      澄清:但我同意,能够访问另一个对象的私有成员是出乎意料的,并且至少部分违反了封装原则。

      【讨论】:

      • “完全没有意义”?假设我引入了一个名为 superprivate 的关键字以及一个超私有类成员只能通过 this 引用访问的规范。所以如果我说superprivate List&lt;Point&gt; points; 那么这个字段points 可以在同一个类的方法中访问,例如points.Add(p); 或等效的 this.points.Add(p)。但是根据superprivate 的规范,说otherCluster.points.Add(p) 是非法的。我认为关键字superprivate 可能是有意义的。它只是比private 更严格,并非毫无意义。
      • 我的意思是,如果不能从同一类的方法中访问 private 字段(实际定义为 private)将毫无意义,因为那时没有人可以访问这个领域。在类的范围内,每个实例成员都自动为this.member。
      • 没错。但看看原来的问题。在那里,cluster.points 与this.points 不同,因为cluster(通常)是this 之外的另一个对象,并且它们的points 列表(通常)会有所不同。当cluster 是不同的对象(来自this)时,原始海报很惊讶可以说cluster.points。因此,另一个对象的实例方法可以看到“私有”实例字段。
      • 嗯,再次阅读您的回答后,我相信我们都同意这一切:-)
      【解决方案4】:

      您在类的范围内定义字段,因此该类中的事物可以访问私有字段。这是定义明确的行为,非常有用,而且编程实践也不错。

      看看Scope可能对你有用。

      【讨论】:

        【解决方案5】:

        private 关键字使字段对类私有,而不是对该类的对象实例。因此,该类中的任何代码都可以访问该类类型的任何对象中的该字段(当然,前提是它具有对该对象的引用)。这样做一点也不坏。

        【讨论】:

          【解决方案6】:

          私有字段在它所在的范围内总是可以访问的 已定义,并且由于私有变量是在类范围内定义的,因此它 可以访问。

          【讨论】:

            【解决方案7】:

            可以在类型内部访问私有字段。 ComputeDistanceToOtherClusterCLINK 是同一个类的成员。所以应该可以从方法体中访问私有字段。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-06-03
              • 2019-08-15
              • 1970-01-01
              • 2011-10-22
              • 2013-06-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多