การใช้ตัวแปรคงที่ใน C # คืออะไร? ควรใช้เมื่อใด เหตุใดฉันจึงไม่สามารถประกาศตัวแปรคงที่ภายในวิธีการ?


106

ฉันได้ค้นหาเกี่ยวกับตัวแปรคงที่ใน C # แต่ฉันยังไม่เข้าใจว่ามันใช้อะไร นอกจากนี้หากฉันพยายามประกาศตัวแปรภายในเมธอดมันจะไม่อนุญาตให้ฉันทำสิ่งนี้ ทำไม?

ฉันได้เห็นตัวอย่างบางส่วนเกี่ยวกับตัวแปรคงที่ ฉันเห็นแล้วว่าเราไม่จำเป็นต้องสร้างอินสแตนซ์ของคลาสเพื่อเข้าถึงตัวแปร แต่นั่นก็ไม่เพียงพอที่จะเข้าใจว่ามันใช้อะไรและควรใช้เมื่อใด

สิ่งที่สอง

class Book
{
    public static int myInt = 0;
}

public class Exercise
{
    static void Main()
    {
        Book book = new Book();

        Console.WriteLine(book.myInt); // Shows error. Why does it show me error?
                                       // Can't I access the static variable 
                                       // by making the instance of a class?

        Console.ReadKey();
    }
}

4
คุณอาจหมายถึง "สนามคงที่"?
Dennis

เหมือนที่เราประกาศในคลาสคง int i = 5
Kartik Patel

3
VB.NET รองรับตัวแปรแบบคงที่ภายในเครื่อง พวกเขาต้องใช้มันเพื่อให้เข้ากันได้กับ vb จำนวนรหัสที่สร้างขึ้นนั้นมหาศาลสถิติในพื้นที่ทำได้ยากเนื่องจากไม่ปลอดภัยต่อเธรด เขตข้อมูลไม่ปลอดภัยต่อเธรด แต่ทุกคนก็คาดหวังเช่นนั้น
Hans Passant

อย่าลืมทำเครื่องหมายคำตอบว่ายอมรับหากคุณมีข้อมูลที่ต้องการ ...
Pranay Rana

3
คุณสามารถเข้าถึงตัวแปรคงที่ / วิธีการผ่านชนิด (ในกรณีนี้Book) ไม่ผ่านอินสแตนซ์ ( book) Book.myIntดังนั้นวิธีการแก้ปัญหาที่ง่ายคือ
Jaider

คำตอบ:


171

staticตัวแปรหุ้นมูลค่าของมันในหมู่ทุกกรณีของชั้นเรียน

ตัวอย่างโดยไม่ต้องประกาศว่าคงที่:

public class Variable
{
    public int i = 5;
    public void test()
    {
        i = i + 5;
        Console.WriteLine(i);
    }
}


public class Exercise
{
    static void Main()
    {
        Variable var = new Variable();
        var.test();
        Variable var1 = new Variable();
        var1.test();
        Console.ReadKey();
    }
}

คำอธิบาย: หากคุณดูตัวอย่างข้างต้นฉันก็แค่ประกาศintตัวแปร เมื่อฉันเรียกใช้รหัสนี้ออกจะเป็นและ10 10มันง่าย

ทีนี้มาดูตัวแปรคงที่นี่ ฉันกำลังประกาศตัวแปรเป็นไฟล์static.

ตัวอย่างที่มีตัวแปรคง:

public class Variable
{
    public static int i = 5;
    public void test()
    {
        i = i + 5;
        Console.WriteLine(i);
    }
}


public class Exercise
{
    static void Main()
    {
        Variable var = new Variable();
        var.test();
        Variable var1 = new Variable();
        var1.test();
        Console.ReadKey();
    }
}

ตอนนี้เมื่อผมทำงานข้างต้นรหัสการส่งออกจะได้รับและ10 15ดังนั้นค่าตัวแปรคงที่ใช้ร่วมกันระหว่างอินสแตนซ์ทั้งหมดของคลาสนั้น


9
@Pranay: ใช่ดีกว่า แต่ถ้าคุณแสดงตัวอย่างที่ฉันแสดงไว้ข้างบนกว่ามันจะดีกว่าสำหรับฉันและคนอื่น ๆ .... อย่างไรก็ตามความพยายามที่ดี ....
Kartik Patel

1
มันคงอยู่กับชั้นเรียนนั่นคือคุณค่าของมันยังคงซื่อสัตย์ต่อชั้นเรียนโดยมีค่าของมันถูกเก็บไว้ในของมัน ... รอก่อน ... ชั้น
chwi

คุณบอกว่าตัวแปรคงที่ใช้ร่วมกันระหว่างอินสแตนซ์ทั้งหมดของคลาส ... แต่ถ้าไม่มีอินสแตนซ์ล่ะ? ยังตั้งค่าตัวแปรได้ไหม อนุญาตให้จัดเก็บข้อมูลแบบไดนามิกในคลาสแบบคงที่หรือไม่
Kokodoko

@Kokodoko แม้ว่าจะไม่มีอินสแตนซ์คุณก็สามารถตั้งค่าตัวแปรได้ ที่กำหนดลักษณะคงที่
Ladmerc

33

C # ไม่มีตัวแปรคงที่เลย คุณสามารถประกาศเขตข้อมูลแบบคงที่ในข้อกำหนดประเภทเฉพาะผ่าน C # ฟิลด์สแตติกคือสถานะที่ใช้ร่วมกับอินสแตนซ์ประเภทใดประเภทหนึ่งทั้งหมด ดังนั้นขอบเขตของฟิลด์คงที่จึงเป็นประเภททั้งหมด นั่นเป็นเหตุผลที่คุณไม่สามารถประกาศเขตข้อมูลแบบคงที่ภายในวิธีการ - วิธีการเป็นขอบเขตเองและรายการที่ประกาศในวิธีการจะต้องไม่สามารถเข้าถึงได้บนเส้นขอบของวิธีการ


5
ในเอกสารระบุว่า "ฟิลด์ที่ประกาศด้วยตัวปรับแต่งคงที่เรียกว่าตัวแปรคงที่" msdn.microsoft.com/en-us/library/aa691162(v=vs.71).aspxแต่คุณพูดถูกต้องตามคำอธิบายที่เหลือ
Teoman shipahi

20

ตัวแปรคงถูกใช้เมื่อต้องการเพียงสำเนาเดียวของตัวแปร ดังนั้นหากคุณประกาศตัวแปรภายในวิธีการไม่มีการใช้ตัวแปรดังกล่าวมันจะกลายเป็นเฉพาะที่ทำงานเท่านั้น ..

ตัวอย่างของคงที่คือ

class myclass
{
    public static int a = 0;
}

ตัวแปรที่ประกาศแบบคงที่มักใช้ร่วมกันในทุกอินสแตนซ์ของคลาส

ตัวแปรที่ประกาศแบบคงที่มักใช้ร่วมกันในทุกอินสแตนซ์ของคลาส เมื่อคุณสร้างหลายอินสแตนซ์ของคลาส VariableTest ตัวแปรถาวรนี้จะถูกแบ่งใช้ในทุกอินสแตนซ์ ดังนั้น ณ ช่วงเวลาใดเวลาหนึ่งจะมีค่าสตริงเพียงค่าเดียวที่อยู่ในตัวแปรถาวร

เนื่องจากมีเพียงสำเนาเดียวของตัวแปรที่ใช้ได้สำหรับทุกอินสแตนซ์โค้ด this.permament จะส่งผลให้เกิดข้อผิดพลาดในการคอมไพล์เนื่องจากสามารถเรียกคืนได้ว่า this.variablename อ้างถึงชื่อตัวแปรอินสแตนซ์ ดังนั้นตัวแปรคงที่สามารถเข้าถึงได้โดยตรงตามที่ระบุไว้ในรหัส


ช่วยอธิบายพร้อมตัวอย่างได้ไหม
Kartik Patel

แต่ถ้าฉันสร้างอินสแตนซ์ของคลาสแล้วฉันไม่สามารถเข้าถึงตัวแปรคงที่ได้ทำไมฉันสามารถเข้าถึงตัวแปรแบบคงที่โดย classname.variable ไม่เพียง แต่สร้างอินสแตนซ์ของคลาสเท่านั้น .......... ......
Kartik Patel

@Kartik Patel เพราะคุณต้องใช้ชื่อคลาสเพื่อเข้าถึง static myInt ทำไมมันเป็นแบบนี้ฉันไม่รู้ แต่ฉันจะบอกว่ามันชัดเจนกว่ามากเพราะคุณต้องการเข้าถึงส่วนคงที่ของคลาสมันไม่คงที่หากคุณต้องการอินสแตนซ์เพื่อเข้าถึง
dowhile สำหรับ

@dowhilefor: แต่อย่างที่คุณได้กล่าวไว้ข้างต้นว่า "ตัวแปรที่ประกาศแบบคงที่มักใช้ร่วมกันในทุกอินสแตนซ์ของคลาส" แล้วความหมายของสิ่งนี้คืออะไร?
Kartik Patel

@Kartik Patel คุณไม่สามารถเข้าถึงตัวแปรจากภายนอกด้วยอินสแตนซ์ได้ แต่คุณสามารถใช้ตัวแปรคงที่ภายในคลาสของคุณได้ตลอดเวลาจากนั้นจะแชร์กับอินสแตนซ์ทั้งหมด ไม่ใช่ฉันที่ให้คำตอบนี้ฉันแค่แสดงความคิดเห็น
dowhile สำหรับ

9

ตัวอย่าง "โลกแห่งความจริง" สำหรับตัวแปรคงที่:

การสร้างคลาสที่คุณสามารถเข้าถึงค่าฮาร์ดโค้ดสำหรับแอปพลิเคชันของคุณ คล้ายกับการแจงนับ แต่มีความยืดหยุ่นมากกว่าในประเภทข้อมูล

public static class Enemies
{
    public readonly static Guid Orc = new Guid("{937C145C-D432-4DE2-A08D-6AC6E7F2732C}");
}

Singleton ที่รู้จักกันอย่างแพร่หลายทำให้สามารถควบคุมให้มีหนึ่งอินสแตนซ์ของคลาสได้ สิ่งนี้มีประโยชน์มากหากคุณต้องการเข้าถึงมันในแอปพลิเคชันทั้งหมดของคุณ แต่อย่าส่งผ่านไปยังทุกชั้นเรียนเพียงเพื่อให้คลาสนี้ใช้งานได้

public sealed class TextureManager
    {
        private TextureManager() {}
        public string LoadTexture(string aPath);

        private static TextureManager sInstance = new TextureManager();

        public static TextureManager Instance
        {
            get { return sInstance; }
        }
    }

และนี่คือวิธีที่คุณเรียกว่า Texturemanager

TextureManager.Instance.LoadTexture("myImage.png");

เกี่ยวกับคำถามสุดท้ายของคุณ: คุณจะหมายถึงข้อผิดพลาดของคอมไพเลอร์CS0176 ฉันพยายามค้นหาข้อมูลเพิ่มเติมเกี่ยวกับสิ่งนั้น แต่สามารถค้นหาสิ่งที่ msdn พูดเกี่ยวกับเรื่องนี้ได้เท่านั้น:

เมธอดแบบคงที่ฟิลด์คุณสมบัติหรือเหตุการณ์สามารถเรียกใช้ได้บนคลาสแม้ว่าจะไม่มีการสร้างอินสแตนซ์ของคลาสก็ตาม หากสร้างอินสแตนซ์ใด ๆ ของคลาสจะไม่สามารถใช้เพื่อเข้าถึงสมาชิกแบบคงที่ได้ มีสำเนาของฟิลด์และเหตุการณ์แบบคงที่เพียงสำเนาเดียวและวิธีการและคุณสมบัติแบบคงที่สามารถเข้าถึงได้เฉพาะเขตข้อมูลแบบคงที่และเหตุการณ์คงที่


5

ตัวแปรคงถูกใช้เมื่อต้องการเพียงสำเนาเดียว ให้ฉันอธิบายสิ่งนี้ด้วยตัวอย่าง:

class circle
{
    public float _PI =3.14F;
    public int Radius;

    public funtionArea(int radius)
    {
        return this.radius * this._PI      
    }
}
class program
{
    public static void main()
    {
        Circle c1 = new Cirle();
        float area1 = c1.functionRaduis(5);
        Circle c2 = new Cirle();
        float area2 = c1.functionRaduis(6);
    }
}

ตอนนี้เราได้สร้าง 2 อินสแตนซ์สำหรับclassแวดวงของเราคือสร้างสำเนา 2 ชุด_PI พร้อมกับตัวแปรอื่น ๆ ดังนั้นสมมติว่าถ้าเรามีอินสแตนซ์ของคลาสนี้หลายสำเนา_PIจะถูกสร้างขึ้นโดยใช้หน่วยความจำ ดังนั้นในกรณีเช่นนี้จึงเป็นการดีกว่าที่จะทำให้ตัวแปรดังกล่าวเหมือน_PI staticและดำเนินการกับตัวแปรเหล่านี้

class circle
{
    static float _PI =3.14F;
    public int Radius;

    public funtionArea(int radius)
    {
        return this.radius * Circle._PI      
    }
}
class program
{
    public static void main()
    {
        Circle c1 = new Cirle();
        float area1 = c1.functionRaduis(5);
        Circle c2 = new Cirle();
        float area2 = c1.functionRaduis(6);
    }
}

ตอนนี้ไม่ว่าจะสร้างอินสแตนซ์สำหรับclassวงกลมกี่ชุดก็มีเพียงสำเนาเดียวของตัวแปรที่_PIบันทึกหน่วยความจำของเรา


4

คลาสแบบคงที่ไม่ต้องการให้คุณสร้างออบเจ็กต์ของคลาสนั้น / สร้างอินสแตนซ์ของคลาสนั้นคุณสามารถนำหน้าคีย์เวิร์ด C # static ไว้หน้าชื่อคลาสเพื่อทำให้มันคงที่

ข้อควรจำ: เราไม่ได้สร้างอินสแตนซ์คลาส Console, คลาส String, Array Class

class Book
{
    public static int myInt = 0;
}

public class Exercise
{
    static void Main()
    {
        Book book = new Book();
       //Use the class name directly to call the property myInt, 
      //don't use the object to access the value of property myInt

        Console.WriteLine(Book.myInt);

        Console.ReadKey();

    }
}

สังเกตดีมากเพราะถ้าคุณพยายามใช้ object เพื่อเข้าถึงค่า property myInt คุณจะได้รับ error: static void Main () {Book book = new Book (); // สิ่งนี้ทำให้คุณมีข้อผิดพลาด: book.myInt = 5;
leonidaa

2

เริ่มจากตัวอย่าง @Kartik Patel นี้ฉันได้เปลี่ยนไปเล็กน้อยตอนนี้อาจมีความชัดเจนมากขึ้นเกี่ยวกับตัวแปรคงที่

 public class Variable
    {
        public static string StaticName = "Sophia ";
        public string nonStName = "Jenna ";
        public void test()
        {
            StaticName = StaticName + " Lauren"; 
            Console.WriteLine("  static ={0}",StaticName);
            nonStName = nonStName + "Bean ";
            Console.WriteLine("  NeStatic neSt={0}", nonStName);

        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Variable var = new Variable();
            var.test();
            Variable var1 = new Variable();
            var1.test();
            Variable var2 = new Variable();
            var2.test();
            Console.ReadKey();

        }
    }

Output 
  static =Sophia  Lauren
  NeStatic neSt=Jenna Bean
  static =Sophia  Lauren Lauren
  NeStatic neSt=Jenna Bean
  static =Sophia  Lauren Lauren Lauren
  NeStatic neSt=Jenna Bean
  1. ตัวแปรคลาส VS ตัวแปรอินสแตนซ์ใน C #

    สมาชิกคลาสแบบคงที่ C # หรือตัวแปรคลาส

    class A
    {
        // Class variable or " static member variable"  are declared with 
        //the "static " keyword
    
        public static int i=20;
        public int j=10;         //Instance variable 
        public static string s1="static class variable"; //Class variable 
        public string s2="instance variable";        // instance variable 
    }
    class Program
    {
        static void Main(string[] args)
        {
            A obj1 = new A();
    
            // obj1 instance variables 
            Console.WriteLine("obj1 instance variables ");
            Console.WriteLine(A.i);
            Console.WriteLine(obj1.j);
            Console.WriteLine(obj1.s2);
            Console.WriteLine(A.s1);
    
            A obj2 = new A();
    
            // obj2 instance variables 
            Console.WriteLine("obj2 instance variables ");
            Console.WriteLine(A.i);
            Console.WriteLine(obj2.j);
            Console.WriteLine(obj2.s2);
            Console.WriteLine(A.s1);
    
            Console.ReadKey();
    
        }
    
    
    }

    }

ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่

https://en.wikipedia.org/wiki/Class_variable

https://en.wikipedia.org/wiki/Instance_variable

https://en.wikipedia.org/wiki/Static_variable

https://javaconceptoftheday.com/class-variables-and-instance-variables-in-java/?fbclid=IwAR1_dtpHzg3bC5WlGQGdgewaTvuOI6cwVeFUtTV8IZuGTj1qH5PmKGwX0yM

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members


1

สมาชิกข้อมูลและสมาชิกฟังก์ชันที่ดำเนินการกับอินสแตนซ์ของประเภทนี้เรียกว่าสมาชิกอินสแตนซ์ เมธอด ToString ของ int (เช่น) เป็นตัวอย่างของสมาชิกอินสแตนซ์ โดยค่าเริ่มต้นสมาชิกคือสมาชิกอินสแตนซ์ สมาชิกข้อมูลและสมาชิกฟังก์ชันที่ไม่ทำงานบนอินสแตนซ์ของประเภท แต่จะต้องทำเครื่องหมายเป็นแบบคงที่ วิธี Test.Main และ Console.WriteLine เป็นวิธีการแบบคงที่ คลาสคอนโซลเป็นคลาสแบบคงที่ซึ่งหมายความว่าสมาชิกทั้งหมดเป็นแบบคงที่ คุณไม่เคยสร้างอินสแตนซ์ของคอนโซลเลยแม้แต่คอนโซลเดียวจะแชร์กับแอปพลิเคชันทั้งหมด


1

เพื่อตอบสนองต่อ "เมื่อใดควรใช้" คำถาม:

ฉันมักจะใช้ตัวแปร (คลาส) แบบคงที่เพื่อกำหนด ID อินสแตนซ์เฉพาะให้กับทุกอินสแตนซ์ของคลาส ฉันใช้รหัสเดียวกันในทุกชั้นเรียนมันง่ายมาก:

//Instance ID ----------------------------------------
    // Class variable holding the last assigned IID
    private static int xID = 0;
    // Lock to make threadsafe (can omit if single-threaded)
    private static object xIDLock = new object();
    // Private class method to return the next unique IID 
    //  - accessible only to instances of the class
    private static int NextIID()                    
    {
        lock (xIDLock) { return ++xID; }
    }
    // Public class method to report the last IID used 
    // (i.e. the number of instances created)
    public static int LastIID() { return xID; }
    // Instance readonly property containing the unique instance ID
    public readonly int IID = NextIID();
//-----------------------------------------------------

สิ่งนี้แสดงให้เห็นสองสามประเด็นเกี่ยวกับตัวแปรคงที่และวิธีการ:

  1. ตัวแปรและวิธีการคงที่มีความสัมพันธ์กับคลาสไม่ใช่อินสแตนซ์เฉพาะของคลาส
  2. สามารถเรียกเมธอดแบบคงที่ในตัวสร้างของอินสแตนซ์ - ในกรณีนี้วิธีการแบบคงที่ NextIID ถูกใช้เพื่อเริ่มต้น IID คุณสมบัติแบบอ่านอย่างเดียวซึ่งเป็น ID เฉพาะสำหรับอินสแตนซ์นี้

ฉันพบว่าสิ่งนี้มีประโยชน์เพราะฉันพัฒนาแอปพลิเคชั่นที่มีการใช้งานออบเจ็กต์เป็นจำนวนมากและเป็นการดีที่จะสามารถติดตามจำนวนที่ถูกสร้างขึ้นและเพื่อติดตาม / สืบค้นอินสแตนซ์แต่ละรายการ

ฉันยังใช้ตัวแปรคลาสเพื่อติดตามสิ่งต่างๆเช่นผลรวมและค่าเฉลี่ยของคุณสมบัติของอินสแตนซ์ซึ่งสามารถรายงานได้แบบเรียลไทม์ ฉันคิดว่าชั้นเรียนเป็นสถานที่ที่ดีในการเก็บข้อมูลสรุปเกี่ยวกับอินสแตนซ์ทั้งหมดของชั้นเรียน



0

เมื่อเปรียบเทียบกับตัวแปรเซสชันตัวแปรคงที่จะมีค่าเท่ากันสำหรับผู้ใช้ทั้งหมดที่พิจารณาว่าฉันกำลังใช้แอปพลิเคชันที่ปรับใช้ในเซิร์ฟเวอร์ หากผู้ใช้สองคนเข้าถึงหน้าเดียวกันของแอปพลิเคชันตัวแปรคงที่จะเก็บค่าล่าสุดไว้และจะให้ค่าเดียวกันกับผู้ใช้ทั้งสองซึ่งแตกต่างจากตัวแปรเซสชันที่แตกต่างกันสำหรับผู้ใช้แต่ละคน ดังนั้นหากคุณต้องการสิ่งที่เหมือนกันและเหมือนกันสำหรับผู้ใช้ทุกคนรวมถึงค่าที่ควรใช้ร่วมกับรหัสแอปพลิเคชันให้ใช้แบบคงที่เท่านั้น


0

คุณไม่จำเป็นต้องสร้างอินสแตนซ์อ็อบเจ็กต์เนื่องจาก yau จะใช้ตัวแปรแบบคงที่: Console.WriteLine (Book.myInt);


-1

ตัวแปรคงที่ยังคงเป็นค่าก่อนหน้าจนกว่าโปรแกรมจะออก Static ถูกใช้โดยการเรียกโดยตรง class_Name.Method () หรือ class_Name.Property ไม่จำเป็นต้องมีการอ้างอิงวัตถุ การใช้คงที่เป็นที่นิยมมากที่สุดคือคลาสคณิตศาสตร์ของ C # Math.Sin (), Math.Cos (), Math.Sqrt ()

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.