在多个类之间共享变量

问题描述 投票:3回答:5

如果我有3个班级,可以说:主班,儿童班,其他孩子。

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(); 

}

这是什么解决方案?

c# .net
5个回答
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
投票

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

public class OtherChild
{
    ChildClass _cc;

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

1
投票

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


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; 

}

0
投票

只是想我会添加你可能实际上想要分享一个类或不同类类型的实例....所以如果实际意图是......

A)..ALL .. ChildClass实例共享您可以使用'静态'的EXACT SAME名称您可以使用属性访问器隐藏成员静态的事实

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

C)此代码的“更好/更清洁”版本(更复杂但更标准):....考虑将成员变量更改为属性如果ALWAYS必须是参考(对共享值)...考虑制作部分如果信息共享必须双向进行,那么'构造函数'就像在其他示例中一样。如果在两个方向上有很多共享信息,则考虑必须将每个指向另一个。考虑将一个单独的SharedInfoClass传递给两者构造函数如果不同类的所有实例共享EXACT SAME信息,那么引用静态类可以避免将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 
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.