在多个类之间共享变量

本文关键字:之间 共享变量 | 更新日期: 2023-09-27 18:36:04

如果我有3个类,假设:Mainclass,ChildClass,OtherChild。

MainClass()
{
     ChildClass cc = new ChildClass();
     OtherChild oc = new OtherChild();
     //Set the name property of childclass
     string childName = "some name";
}
ChildClass()
{
    public string name {get; set;}
}
OtherChild()
{
     //Here i want to get the name property from ChildClass()
     //Doing this will make a new instance of ChildClass,  which will not have the name property set.
     ChildClass cc = new ChildClass(); 
}

解决方案是什么?

在多个类之间共享变量

基本上,为了在类之间访问信息,您必须在实例之间以某种方式"传递"该信息。

下面是使用基本设置的快速注释示例。我提供了一些可以在对象之间发送信息的不同方法的示例:

public MainClass()
{
    // just using auto-properties here. Will need initialized before use.
    public ChildClass cc { get; set; }
    public OtherChild oc { get; set; }
     // Constructor. Gets called when initializing as "new MainClass()"
     public MainClass() 
     {                
        // initialize our properties
        // option 1 - initialize, then set
        cc = new ChildClass();
        cc.childName = "some name"; //Set the name property of childclass
        //option 2 - initialize and set via constructor
        cc = new ChildClass("some name");
        // option 3 - initialize and set with initializer (more here: http://msdn.microsoft.com/en-us/library/vstudio/bb397680.aspx)
        cc = new ChildClass() { name = "some name" };
        oc = new OtherChild(cc);
     }
}
public ChildClass()
{
    public string name { get; set; }
    // Default constructor. this.name will = null after this is run
    public ChildClass() 
    {                
    }
    // Other constructor. this.name = passed in "name" after this is run
    public ChildClass(string name) 
    {
        //"this.name" specifies that you are referring to the name that belongs to this class
        this.name = name;
    }
}
public OtherChild()
{
    public ChildClass cc { get; set; } 
    public OtherChild() 
    {        
       cc = new ChildClass(); // initialize object in the default constructor
    }
    public OtherChild(ChildClass childClass) 
    {        
       cc = childClass; // set to the reference of the passed in childClass
    }
}

当然,这些都使用.NET 的自动属性。对于简单的实现,它们工作正常。但是,如果您需要(或只是想要)拆分成员,下面是一个使用完整属性语法的示例。

public MainClass()
{
    // private backing field is only accessible within this class
    private ChildClass _cc = new ChildClass();
    // public property is accessible from other classes
    public ChildClass cc 
    { 
        get 
        {
            return _cc;
        }
        set
        {
            _cc = value;
        }
    }
}

如果您注意到,这会在成员声明的开头初始化私有_cc。这可确保在使用前不需要显式初始化 cc 属性。同样,这与其说是一个严格的标准,不如说是一个例子。了解 .NET 使用属性和私有成员的所有方式非常重要,因此你可以选择并使用最适合你的特定情况的属性和私有成员。


另外,作为旁注,您会注意到我在每个私有成员、属性和构造函数前面都包含privatepublic。虽然在技术上不是必需的,但通常最好为每个类成员显式指定可访问性级别(这会促进封装)。维基百科关于封装的文章有一个相当不错的介绍性解释和示例。

对于将来,我还建议查看一组 .NET 命名约定,例如属性名称、支持字段、方法名称等:

  • .net 命名约定和编程标准 - 最佳做法(快速参考)
  • MSDN 的框架设计指南(更广泛)

虽然您可能可以很好地阅读自己的代码,但遵循这些不同的命名约定可确保其他人也能够更好地阅读和理解它。

只是想我会补充一下,您可能实际上想在类的实例之间共享或不同的类类型。因此,如果实际意图是...

A) ..都。。ChildClass 的实例共享完全相同的名称,您可以使用"静态" 您可以使用属性访问器隐藏成员是静态的事实

B)不同类型的类的不同实例需要共享信息。 然后,实例化类时的交叉引用起作用 (在本例中,子类和其他子类是不同的类类型) 在此示例中 您实际上希望能够随时在一个实例中更改信息 并且仍然与其他实例共享该新信息...

C)此代码的"更好/更干净"版本(更复杂但更标准): ....考虑将成员变量更改为属性 如果总是必须是一个参考(对共享值)...考虑像其他示例一样成为"构造函数"的一部分 如果信息共享必须双向进行。考虑必须将彼此指向另一个 如果有很多双向共享信息..考虑将单独的 SharedInfoClass 传递给两个构造函数 如果不同类的所有实例共享完全相同的信息,则引用静态类可以避免将 SharedInfoClass 传递给构造函数的需要 被认为比"静态类"更干净(但更复杂)的是单例设计模式

解决方案 A

********
// ... information shared across all instances of a class
// Class A  a1,a2;    a1,a2  share exact same values for certain members
class MainClass
{
     void Method()
    {
         ChildClass cc = new ChildClass();
         OtherChild oc = new OtherChild();
         //Set the name property of childclass
         ChildClass.s_name = "some name"; // obviously a shared static because using ChildClass.members not cc.member
         cc.Name = "some name";  // now all instances of ChildClass will have this name
    }
}

class ChildClass
{
    // *** NOTE  'static' keyword ***
    public static string s_name;   // externally refered to by ChildClass.s_name
    // this property hides that s_name is a static which is good or bad depending on your feelings about hiding the nature of data
    public string Name           
    {
        get
        {
            return s_name;
        }
        set // singleton so never set only created first use of get
        {
            s_name = value;
        }
    }
}
class OtherChild
{
    public OtherChild()
    {
    }
    void Method()
    {
        ChildClass cc = new ChildClass();
        string str = cc.Name;
        // cc will have the same name as the cc in MainClass
    }
}

解决方案 B

**********
class BMainClass
{
    void Method()
    {
        BChildClass cc = new BChildClass();
        BOtherChild oc = new BOtherChild( );
        oc.m_SharedChildClassInfo = cc;
        //Set the name property of childclass
        cc.name = "some name";  // only this instance of BChildClass will have this name, but it visible in BOtherChild
    }
}
class BChildClass
{
    public string name {get; set;}
}
class BOtherChild
{
    public BChildClass m_SharedChildClassInfo;
    void Method()
    {
        BChildClass cc = m_SharedChildClassInfo; 
        // cc will have the same name as the cc in MainClass
        // in fact it is the exact same instance as declared in MainClass so evetythng is the same
    }
}

解决方案 C

******
// this one example shows both 
//  a set of data shared across all instances of two class
//  and a set of data sharted between 2 specific classes
class CMainClass
{
    void Method()
    {
        CSharedBetweenSome sharedSomeInstances = new CSharedBetweenSome();
        CChildClass cc = new CChildClass(sharedSomeInstances);
        COtherChild oc = new COtherChild(sharedSomeInstances);
        //Set the name property of childclass
        cc.sharedAllValue = "same name for everyone";  // ALL  instance of ChildClass will have this name, ALL instances BOtherChild will be able to acess it
        sharedSomeInstances.name = "sane name for cc and oc instances";
    }
}
// Interface - sometimes to make things clean / standard between different classes defining an interface is useful
interface ICShareInfoAll
{
    string sharedAllValue { get; set; }
}
class CSharedInto : ICShareInfoAll
{
    // Singletone pattern - still an instance, rather than a static, but only ever one of them, only created first time needed
    private static CSharedInto s_instance;
    public static CSharedInto Instance
    {
        get
        {
            if( s_instance == null )
            {
                s_instance = new CSharedInto();
            }
            return s_instance;
        }
        private set // singleton  never set only created first use of get
        {
            //s_instance = value;
        }
    }
    // variables shared with every instance of every type of child class
    public string sharedAllValue { get; set; }
}
// One child class using  jointly shared and shared with all
class CChildClass :  ICShareInfoAll
{
    private CSharedBetweenSome sharedSomeInstance;
    public CChildClass(CSharedBetweenSome sharedSomeInstance)
    {
        this.sharedSomeInstance = sharedSomeInstance;
    }
    // Shared with all 
    public string sharedAllValue {
        get { return CSharedInto.Instance.sharedAllValue;  }           
        set { CSharedInto.Instance.sharedAllValue = value; }
        }
    // Shared with one other
    public string sharedAnotherInstanceValue {
        get { return sharedSomeInstance.name;  }           
        set { sharedSomeInstance.name = value; }
        }
}
class COtherChild :  ICShareInfoAll
{
    private CSharedBetweenSome sharedSomeInstance;
    public COtherChild(CSharedBetweenSome sharedSomeInstance)
    {
        this.sharedSomeInstance = sharedSomeInstance;
    }
    public string sharedAllValue {
        get { return CSharedInto.Instance.sharedAllValue;  }           
        set { CSharedInto.Instance.sharedAllValue = value; }
        }
    void Method()
    {
        string val = sharedAllValue;  // shared across instances of 2 different types of class
        string val2 = sharedSomeInstance.name;  // currenlty shared across spefic instances 
    }
}

如果我正确理解你的问题,这可以工作。请注意,我的语法可能是错误的,因为我对 c# 不是很流利,但我希望你能得到基本的想法

MainClass()
{
     ChildClass _cc = new ChildClass();
     OtherChild _oc = new OtherChild();
     ChildClass cc = get {return _cc;} set{_cc = value;}
     OtherChild oc = get {return _oc;} set{_oc = value;}
     oc.Parent = this;
     //Set the name property of childclass
     string childName = "some name";
}
ChildClass()
{
    public string name {get; set;}
}
OtherChild()
{
     //Here i want to get the name property from ChildClass()
     //Doing this will make a new instance of ChildClass,  which will not have the name property set.
     Public MainClass parent {get; set;}
     ChildClass cc = parent.cc; 
}

为 OtherChild 创建一个构造函数,该构造函数采用 ChildClass 的实例,或者只使用 name 属性(如果这是您所需要的)。

public class OtherChild
{
    ChildClass _cc;
    public OtherChild(ChildClass cc)
    {
        this._cc = cc;
    }
}

最简单的答案很可能是,您应该简单地将名称传递给两个子类,而不是将其传递给一个类,然后让这些兄弟姐妹相互交谈。 当您设置ChildClass的名称时,只需同时设置OtherClass的名称即可。