【问题标题】:static member inside constructor in C#C#构造函数中的静态成员
【发布时间】:2013-01-16 13:00:29
【问题描述】:

通常我们知道,为了访问 静态 变量,我们不需要创建类的实例。我们可以直接点赞classname.staticvariable。为了访问类中的静态变量,我们应该有一个静态方法。

现在我对下面的代码 sn-p 有疑问

public class xyz
{
    private static int a;

    public xyz()
    {
        a++;
    }
}

上面的代码 sn-p 会起作用吗?如果是,为什么,如果不是,为什么?

谢谢 普拉班詹

【问题讨论】:

  • 它会起作用吗?你有一个编译器。试试看。
  • 显然更快地发布到 SO。
  • 情况正好相反。你不能在静态方法中使用非静态变量,而你可以在非静态方法中使用静态变量(但你需要记住并发问题)。
  • 请注意,a 在使用 Thread 时并不总是包含创建的xyz 的数量。多个线程可以一次访问该变量并留下不可预测的结果。

标签: c# oop variables static


【解决方案1】:

是的,它会的。 int 的默认值为 0。每次调用构造函数时,都会增加静态变量。

【讨论】:

  • 解释当 a 设置为 0
  • 这将在 CLR 级别:) 但是一旦你点击你的变量并且它还没有被启动它就会得到它的默认值。如果是 int 则为 0
  • 好的,但我的问题是非静态成员函数(构造函数也是一个特殊的成员函数,没有任何返回类型并具有类的名称)如何访问静态变量?
  • 静态成员对您的对象的任何实例都有效。每次访问对象时,它都是相同的值。所以非静态方法(构造函数)可以访问静态变量。但它将与该对象的所有其他实例共享。如果您愿意,您甚至可以编写一个静态方法来读取您的静态变量以获取它的值,甚至无需创建对象。
  • 您甚至可以通过创建静态默认构造函数来将静态变量的默认值设置为另一个值,并在其中分配自定义值
【解决方案2】:

从实例方法访问静态成员非常好。

静态变量a 的默认值为0,您的代码会在您每次创建该类的实例时递增它。

【讨论】:

    【解决方案3】:

    上面的 sn-p 可以正常工作。编写此类代码是为了计算类中存在的活动实例的数量。

    public class xyz
    {
        private static int a;
    
        public xyz()
        {
            a++;
        }
    
        public static int A
        {
            get { return a;}
        }
    }
    

    将活动实例的数量打印为:

    Console.WriteLine(obj.A);
    

    【讨论】:

    • 但是为什么非静态成员函数访问静态成员函数在这种情况下它是一个构造函数?
    • 您可以在非静态方法中访问静态变量。但不允许反过来。
    【解决方案4】:

    有效。

    假设你想知道一个类的实例已经创建了多少。所以在这种情况下你可以使用

    xyz.a 
    

    您还可以创建一个析构函数并使用a-- 来监控活动实例的数量。

    【讨论】:

    • 是的,它工作正常,但非静态成员函数(构造函数)如何能够访问静态成员?
    • 静态成员以某种方式在所有非静态成员(实例成员)之间共享。 -我不确定我是否听懂了你的评论问题!-
    【解决方案5】:

    以下假设不正确;

    为了访问类中的静态变量,我们应该有 静态方法。

    您提供的代码有效,因为您不需要静态方法。

    试试下面的,你会发现它也有效;

    public class xyz
    {
        private static int a;
    
        public void A()
        {
            a++;
        }
    }
    

    【讨论】:

    • 为什么我不需要静态方法?
    • @PrabhanjanKumarMahapatra 因为要访问静态变量,您不需要将方法声明为静态。
    【解决方案6】:

    是的,它会起作用。您可以在实例成员中引用静态成员,但不能在静态成员中引用实例成员,因为它们需要实例才能工作,而静态不需要。

    【讨论】:

    • 好的,那么如何在非静态方法(构造函数)中访问静态变量?
    • 你在问语法或原因是什么意思?
    • static 表示所有实例通用。为什么你认为它无法访问?
    • 这就是我试图找出为什么静态对所有实例都意味着通用以及如何在非静态成员函数中访问静态的原因?
    【解决方案7】:

    它不起作用 如果你想访问静态变量,你必须公开它 和 构造函数方法不运行,因为构造函数在您使用初始化类并创建对象时运行。

    【讨论】:

    • Edalat.. 它可以正常工作...当然,tpeczek 正在回答它的工作原理(在其中一条评论中)
    • 他想在不初始化 xyz 类的情况下访问 var "Private" a。
    • 他正在访问来自 within 类的 private 变量。这是有效的。静态变量在类第一次被访问时被初始化——所以变量将在使用instance constructor之前被初始化。这里没有错。
    • JustAnotherUserYouMayKnow...很多。
    【解决方案8】:

    引用C# documentation on static variables

    静态成员在访问静态成员之前被初始化 第一次和在静态构造函数之前,如果有, 被调用。

    例如运行以下示例程序:

    using System;
    
    namespace ScrapCSConsole
    {
       class ScrapCSConsole
       {
          public static void Main()
          {
             Console.WriteLine("Create StaticDemo A");
             StaticDemo a = new StaticDemo();
             Console.WriteLine("Create StaticDemo B");
             StaticDemo b = new StaticDemo();
             Console.WriteLine("Done");
          }
       }
    
       class StaticDemo
       {
          private static int staticDemo1;
          private static int staticDemo2 = 0;
          private static int staticDemo3 = default(int);
          private static int staticDemo4;
          private static int classNumber;
    
          /// <summary>
          /// Static Constructor
          /// </summary>
          static StaticDemo()
          {
             Console.WriteLine("Static Constructor");
             Console.WriteLine("staticDemo1 {0}", staticDemo1);
             staticDemo4 = (new DateTime(1999, 12, 31)).DayOfYear;
          }
    
          /// <summary>
          /// Instance Constructor
          /// </summary>    
          public StaticDemo()
          {
             classNumber++;
             Console.WriteLine("classNumber {0}", classNumber);
             Console.WriteLine("staticDemo2 {0}", staticDemo2);
             Console.WriteLine("staticDemo3 {0}", staticDemo3);
             Console.WriteLine("staticDemo4 {0}", staticDemo4);                  
          }      
       }
    }
    

    你会得到以下输出:

    Create StaticDemo A
    Static Constructor 
    staticDemo1 0
    classNumber 1
    staticDemo2 0
    staticDemo3 0
    staticDemo4 365
    Create StaticDemo B
    classNumber 2
    staticDemo2 0
    staticDemo3 0
    staticDemo4 365
    Done
    

    这里有一些有趣的事情需要注意:

    1. 'Console.WriteLine("Create StaticDemo A")' 行在 StaticDemo 的静态构造函数之前被调用。
    2. 'Console.WriteLine("Static Constructor")' 行只被调用一次。
    3. 'Console.WriteLine("staticDemo1 {0}", staticDemo1)' 行工作,即使 staticDemo1 从未被显式初始化。
    4. staticDemo1、staticDemo2 和 staticDemo 3 的值均以 0 开头。

    最后,作为一个子注释,如果您在多个线程上创建对象,您需要小心。这是因为 classNumber++ 不是原子操作。它算作两次单独的操作,一次读取和一次写入。因此,两个单独的线程都可以在其中一个线程写出递增值之前读取变量。为避免这种情况,请改用此行:

    System.Threading.Interlocked.Increment(ref classNumber);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      • 1970-01-01
      • 2020-07-15
      相关资源
      最近更新 更多