在多个类之间共享变量

时间:2013-10-20 17:50:01

标签: c# .net

如果我有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(); 

}

这是什么解决方案?

5 个答案:

答案 0 :(得分:6)

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

以下是使用基本设置的快速注释示例。我已经列举了一些关于在对象之间发送信息的不同方法的示例:

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的auto-properties。对于简单的实现,它们工作正常。但是,如果您需要(或者只是想)拆分成员,请使用完整属性语法。

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。虽然不是技术上必要的,但通常的做法是明确指定每个类成员的可访问性级别(这促进了封装)。 The Wikipedia article on encapsulation有一个相当不错的介绍性解释和例子。

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

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

答案 1 :(得分:1)

为OtherChild创建一个构造函数,该构造函数接受ChildClass的实例,或者只是name属性(如果这就是你需要的那样)。

public class OtherChild
{
    ChildClass _cc;

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

如果我正确理解你的问题,这可行。请注意,我的语法可能有误,因为我不是非常流利于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; 

}

答案 4 :(得分:0)

只是想我会添加您可能实际上想在一个类的各个实例之间共享 或不同的班级类型。 因此,如果实际意图是...

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

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

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 
    }
}