C# 在多个类之间共享变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19480747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:06:40  来源:igfitidea点击:

Share variable between multiple classes

c#.net

提问by Chancho

If i have 3 classes, lets say: Mainclass, ChildClass, OtherChild.

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

}

What is the solution for this ?

对此有什么解决方案?

采纳答案by valverij

Basically, in order to access information from class to class, you must "pass" that information in some way between instances.

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

Here is a quick annotated example using your basic setup. I have included a few examples of different ways you could go about sending information between objects:

这是使用您的基本设置的快速注释示例。我已经包含了一些可以在对象之间发送信息的不同方式的示例:

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

Of course, those all use .NET's auto-properties. For simple implementations, they work fine. If, however, you needed to (or just wanted to) split a member out, here is an example using the full property syntax.

当然,这些都使用 .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;
        }
    }
}

If you notice, this initializes the private _ccat the beginning, in the member declaration. This ensures that the ccproperty does not need to be explicitly initialized before use. Again, this is more an example than a rigid standard. It's important to know all of the ways .NET uses properties and private members, so you may choose and use the best one for your particular situation.

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



Also, as a side note, you'll notice that I included either privateor publicin front of each private member, property, and constructor. While not technicallynecessary, it is generally good practice to explicitly specify your level of accessibility for each class member (this promotes encapsulation). The Wikipedia article on encapsulationhas a pretty decent introductory explanation and examples.

此外,作为一个侧面说明,你会发现,我既包含privatepublic在每个私有成员,属性和构造函数的前面。虽然在技术上不是必需的,但为每个类成员明确指定您的可访问性级别通常是一种很好的做法(这会促进封装)。维基百科关于封装的文章有一个相当不错的介绍性解释和例子。

For the future, I'd also suggest taking a look at a set of .NET naming conventions for things such as property names, backing fields, method names, etc:

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

While you may be fine reading your own code, following these different naming conventions ensures that others will be more able to read and understand it as well.

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

回答by Dan Drews

If I correctly understand your question, this can work. Note, my syntax may be wrong as I'm not super fluent at c# but I hope you can get the basic idea

如果我正确理解你的问题,这可以工作。请注意,我的语法可能有误,因为我对 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; 

}

回答by Jason

Create a constructor for OtherChild that takes an instance of ChildClass, or just the name property if that is all you need.

为 OtherChild 创建一个构造函数,该构造函数采用 ChildClass 的实例,或者如果您只需要 name 属性,则可以。

public class OtherChild
{
    ChildClass _cc;

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

回答by Servy

The easiest answer is most likely that you should simply pass the name along to both child classes, instead of passing it along to one class and then having those siblings talk to each other. When you set the name of ChildClass, just set the name of OtherClassat the same time.

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

回答by PJJ

Just thought I would add you might actually want to share across instances of a class or different class types.... So if the actual intent is...

只是想我会补充你可能真的想在一个类的实例或不同的类类型之间共享......所以如果实际意图是......

A) ..ALL.. instances of ChildClass share the EXACT SAME name you can use 'static' You can hide the fact the member is static with a Property accessor

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

B) DIFFERENT instances of DIFFERENT types of class need to share info. then a cross-reference when the classes are instantiated works (ChildClass and OtherChild being different class types in this example) In this example you actually want to be able to change the info in one instance at any time and still share that new info with the other instance...

B) 不同类型的类的不同实例需要共享信息。然后当类被实例化时交叉引用工作(在这个例子中 ChildClass 和 OtherChild 是不同的类类型)在这个例子中,你实际上希望能够随时更改一个实例中的信息,并且仍然与另一个例子...

C) 'better/cleaner' versions of this code (more complex but more standard): ....consider changing the member variable to a property if ALWAYS has to be a reference (to the shared value)... consider making part of the 'constructor' as in other examples if the sharing of information has to go both ways.. consider having to point each to the other if there is a lot of shared info going in both directions.. consider a separate SharedInfoClass passed to both constructors if ALL instances of different classes share the EXACT SAME info then referencing a static class can avoid the need to pass the SharedInfoClass to constructor Regarded as cleaner (but more complex) than a 'static class' is the singleton design pattern

C)此代码的“更好/更干净”版本(更复杂但更标准):....考虑将成员变量更改为属性,如果始终必须是引用(共享值)...考虑制作一部分如果信息共享必须双向进行,则与其他示例中的“构造函数”相同。如果不同类的所有实例共享完全相同的信息,则引用静态类可以避免将 SharedInfoClass 传递给构造函数的需要 被视为比“静态类”更清晰(但更复杂)的是单例设计模式

********** Solution A ******************

********** 解决方案 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
    }
}

********* Solution B ******************

********* 解决方案 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
    }
}

********** Solution C ******************

********** 解决方案 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 
    }
}