จะใช้ Global Variables ใน C # ได้อย่างไร?


104

ฉันจะประกาศตัวแปรเพื่อให้ทุกคลาส (* .cs) เข้าถึงเนื้อหาได้อย่างไรโดยไม่มีการอ้างอิงอินสแตนซ์

คำตอบ:


128

ในC#คุณไม่สามารถกำหนดตัวแปรทั่วโลกที่แท้จริงได้ (ในแง่ที่ว่าพวกเขาไม่ได้เป็นของคลาสใด ๆ )

สิ่งนี้ถูกกล่าววิธีที่ง่ายที่สุดที่ฉันรู้ในการเลียนแบบคุณลักษณะนี้ประกอบด้วยการใช้ a static classดังนี้:

public static class Globals
{
    public const Int32 BUFFER_SIZE = 512; // Unmodifiable
    public static String FILE_NAME = "Output.txt"; // Modifiable
    public static readonly String CODE_PREFIX = "US-"; // Unmodifiable
}

จากนั้นคุณสามารถดึงค่าที่กำหนดไว้ที่ใดก็ได้ในโค้ดของคุณ (หากเป็นส่วนหนึ่งของเดียวกันnamespace):

String code = Globals.CODE_PREFIX + value.ToString();

ในการจัดการกับเนมสเปซที่แตกต่างกันคุณสามารถ:

  • ประกาศGlobalsชั้นเรียนโดยไม่รวมไว้ในเฉพาะnamespace(เพื่อที่จะวางไว้ในเนมสเปซแอปพลิเคชันส่วนกลาง)
  • namespaceใส่ที่เหมาะสมโดยใช้คำสั่งสำหรับการดึงตัวแปรจากที่อื่น

@ Zarathos ชั้นต้องนิ่งด้วยเหรอ?
kosnkov

4
มันไม่จำเป็น แต่ฉันไม่เห็นว่าทำไมคุณควรอินสแตนซ์มัน
Tommaso Belluzzo

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

สวัสดีจะมีความแตกต่างอย่างไรถ้าฉันไม่พิมพ์คำหลักแบบคงที่ในคลาส ฉันทำให้สตริง FILE_NAME คงที่เท่านั้นฉันลองแล้วและยังใช้งานได้
Tomer Cahal

1
หากไม่มีแอตทริบิวต์คงที่คลาสของคุณจะสามารถทำได้ทันที (Globals g = new Globals ()) มันไม่ได้เปลี่ยนแปลงพฤติกรรมของตัวแปรคงที่ที่ประกาศไว้ภายใน แต่มันดูไม่มีประโยชน์จริงๆ
Tommaso Belluzzo

74

ไม่มีสิ่งที่เรียกว่าตัวแปรส่วนกลางใน C # ระยะเวลา

คุณสามารถมีสมาชิกแบบคงที่ได้หากคุณต้องการ:

public static class MyStaticValues
{
   public static bool MyStaticBool {get;set;}
}

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

3
@cawas เพราะแนวคิดเรื่อง "ตัวแปรระดับโลก" (ห้อยลงมาจากไหนไม่รู้ลอยอยู่ในบริเวณขอบรกไม่ได้เป็นของชนชั้นใด ๆ ) ขัดกับธรรมชาติของ OOP และ C # เป็นวัตถุอย่างเคร่งครัด
Federico Berasategui

ใช่นั่นคือแนวคิดทั้งหมดที่ฉันเห็นด้วย แต่การสร้างสมาชิกแบบคงที่นั้นคุณเพิ่งสร้าง global var. มันแตกต่างจากตัวแปรทั่วโลกที่คุณบอกว่าไม่มีอยู่อย่างไร ฉันต้องการดูตัวอย่างที่ใช้ได้จริง
cregox

1
ฉันรู้สึกว่าคุณกำลังหลบเลี่ยงคำถามของฉันหรือฉันไม่ชัดเจน แต่ฉันได้รับคำตอบแล้ว ที่นี่: stackoverflow.com/a/20010543/274502
cregox

7
ตอนนี้ฉันรู้แล้วว่าฉันหมายถึงอะไรก็คือสมาชิกแบบคงที่เป็นตัวแทนเชิงแนวคิดและในทางปฏิบัติทั่วโลก (ยกเว้นบางทีสำหรับสิ่งที่ฮีปนั้นซึ่งสร้างความแตกต่างเว้นแต่คุณจะเขียนโค้ดที่ไม่ปลอดภัยหรือทำงานร่วมกันอย่างหนักกับโค้ดที่ไม่มีการจัดการ ) ผมไม่รู้ว่าทำไมใคร ๆ ก็บอกว่า " ไม่มี global variable ใน csharp " มันทำให้ฉันสับสนมาก
cregox

23

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

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

  1. รวมตัวแปร Global ทั้งหมดไว้ในไฟล์เดียว staticคลาส (เพื่อความสามารถในการจัดการ)
  2. มีคุณสมบัติแทนฟิลด์ (= 'ตัวแปร') ด้วยวิธีนี้คุณจะมีกลไกบางอย่างในการแก้ไขปัญหาเกี่ยวกับการเขียนพร้อมกันไปยัง Globals ในอนาคต

โครงร่างพื้นฐานสำหรับชั้นเรียนดังกล่าวจะเป็น:

public class Globals
{
    private static bool _expired;
    public static bool Expired 
    {
        get
        {
            // Reads are usually simple
            return _expired;
        }
        set
        {
            // You can add logic here for race conditions,
            // or other measurements
            _expired = value;
        }
    }
    // Perhaps extend this to have Read-Modify-Write static methods
    // for data integrity during concurrency? Situational.
}

การใช้งานจากคลาสอื่น ๆ (ภายในเนมสเปซเดียวกัน)

// Read
bool areWeAlive = Globals.Expired;

// Write
// past deadline
Globals.Expired = true;

5

คุณสมบัติที่มีประโยชน์สำหรับสิ่งนี้คือ using static

อย่างที่คนอื่นบอกคุณต้องสร้างคลาสสำหรับลูกโลกของคุณ:

public static class Globals {
    public const float PI = 3.14;
}

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

using static Globals;
[...]
Console.WriteLine("Pi is " + PI);

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