在 C 语言中的类之间共享对象#

Share objects between classes in C#

提问人:Ignacio 提问时间:3/20/2019 最后编辑:Ignacio 更新时间:3/21/2019 访问量:2625

问:

如果两个类具有相同的键(它只是一个字符串),我希望两个类共享一个对象,因此如果对象的值发生变化,它会在两个类中更改。我认为这就像让两个对象指向相同的内存地址一样,所以在 C 中可以使用指针来完成。为了阐明我想做什么,我准备了下一个示例代码:

class MyObject
{
    string key;
    int value;

    public MyObject(string key, int value)
    {
        this.key = key;
        this.value = value;
    }
}

class MainClass{

    MyObject parameter = new MyObject("key", 5);
    List<MyObject> list = new List<MyObject>();
    list.Add(parameter);

}

class SecondaryClass{

    MyObject parameter = new MyObject("key", 0);
    List<MyObject> list = new List<MyObject>();
    list.Add(parameter);
}

MainClass mainClass = new MainClass();
SecondaryClass secondaryClass = new SecondaryClass();

foreach (MyObject newParameter in mainClass.list)
{
    // Try to find a match in the parameterKey
    MyObject parameter = secondaryClass.list.Find(p => p.Key == newParameter.Key);

    // If there is a match, update the object
    if (parameter != null)
    {
        parameter = newParameter;
    }
}

Console.WriteLine(mainClass.parameter.value) // This output 5

Console.WriteLine(secondaryClass.parameter.value) // This output 0

看到 secondaryClass 的参数仍然指向 0,该值尚未更新。可以在 C# 中做到这一点吗?也许分享参考资料?

---编辑---

我现在按照 Jon Skeet 的要求包括一个最小、完整和可验证的示例。

class MyObject
{
    public string key;
    public int value;

    public MyObject(string key, int value)
    {
        this.key = key;
        this.value = value;
    }
}

class MainClass
{

    public MyObject parameter = new MyObject("key", 5);
    public List<MyObject> list = new List<MyObject>();

    public MainClass()
    {
        list.Add(parameter);
    }
}

class SecondaryClass
{

    public MyObject parameter = new MyObject("key", 0);
    public List<MyObject> list = new List<MyObject>();

    public SecondaryClass()
    {
        list.Add(parameter);
    }
}

class Program
{
    static void Main(string[] args)
    {
        MainClass mainClass = new MainClass();
        SecondaryClass secondaryClass = new SecondaryClass();

        foreach (MyObject newParameter in mainClass.list)
        {
            // Try to find a match in the parameterKey
            MyObject parameter = secondaryClass.list.Find(p => p.key == newParameter.key);

            // If there is a match, update the object
            if (parameter != null)
            {
                parameter = newParameter;
            }
        }

        Console.WriteLine(mainClass.parameter.value); // This output 5
        Console.WriteLine(secondaryClass.parameter.value); // This output 0, I expected 5

        mainClass.parameter.value = 7;
        Console.WriteLine(mainClass.parameter.value); // This output 7
        Console.WriteLine(secondaryClass.parameter.value); // This output 0, I expected 7

    }
}

正如你所看到的,对象 secondaryClass.parameter 没有改变,静止图像指向原始对象。当然,如果它只有一个对象,我可以在末尾添加这两行:

secondaryClass.parameter = mainClass.parameter;
mainClass.parameter.value = 9;

Console.WriteLine(mainClass.parameter.value); // This output 9
Console.WriteLine(secondaryClass.parameter.value); // This output 9

主要存在两个问题:

  • MyObject 比此处显示的更复杂,但更多 属性。

  • MainClass 和 SecondaryClass 有多个对象 MyObject,只需要共享具有相同键的对象(并且两个类都可以不共享 MyObject 对象)。

C# .NET 按引用传递

评论

1赞 Pac0 3/20/2019
只有快速阅读,这不是一个答案,但仅供参考,所有对象(类)变量都包含对 C# 中对象的引用。 (if 是一个类)。顺便说一句,出于同样的原因,类也被称为引用类型var a = new Something(); var b = a; // now b refers to the *exact same object as a* in memorySomething
0赞 Ignacio 3/20/2019
@Pac0是的,我期待这一点,但事实并非如此。
1赞 Jon Skeet 3/20/2019
很难确切地理解您在寻找什么,因为您只发布了伪代码。请提供一个最小的可重复示例
1赞 RICKY KUMAR 3/20/2019
使用字典太容易了。
2赞 Ignacio 3/20/2019
@JonSkeet做完了,下次我会从头开始就这样做

答:

2赞 S. Schenkel 3/20/2019 #1

使用 ,ur 只是修改其引用是局部变量。 您没有在 secondaryClass 列表中修改对象的引用。parameter = newParameterMyObject parameter

评论

0赞 Pac0 3/20/2019
这正是造成混乱的原因。
0赞 Pac0 3/20/2019 #2

S. Schenkel 描述了问题的原因:您只是用当前的伪代码重新分配局部变量。

例如,如果要更新“引用”的实际对象,可以执行以下操作来访问实际对象并更改实际的感兴趣字段:

您可以像这样访问实际对象,例如:

if (parameter != null)
{
    parameter.value = newParameter.value;
}

但是,您应该创建一个公共字段或带有公共二传手的财产才能做到这一点。value


当然,这只是为了让你明白这一点。

也许你应该做一些更清晰/更好地封装的事情,如下所示:

class SecondaryClass
{
    public MyObject parameter = new MyObject("key", 0);
    public List<MyObject> list = new List<MyObject>();

    public SecondaryClass()
    {
        list.Add(parameter);
    }

    public UpdateParameter(MyObject newParameter, string key) 
    {
        // here you can write code that can *directly* access your field or list.
        // you can, for instance, search for the object by key in the list, delete it from the list, and add `newParameter` to the list
        // and reassign "parameter" with this new object.
    }
}

请注意,如果此“UpdateParameter”方法中存在键,您现在可以推迟搜索的负担。

你的“主”代码可以变成这样:

    foreach (MyObject newParameter in mainClass.list)
    {
        // Try to find a match, and update it in the parameterKey
        secondaryClass.UpdateParameter(newParameter);
    }

注意:我不明白使用参数“列表”的想法,此外还有一个存储单个参数的字段。

如建议,如果您有多个键值对,则应使用 a 作为 MainClass 和 SecondaryClass 的内部字段,这将大大简化代码的访问和可读性。Dictionary<string, MyObject>

评论

0赞 Ignacio 3/20/2019
这只会更新值,而不会更新对象本身。我包含了新代码,可以看出在最后一行中我希望两个对象是相同的。
0赞 Pac0 3/20/2019
@Ignacio :您必须创建一些代码来执行更新,例如SecondaryClass的方法。为了更好地理解:你有一个引用对象的字段。在其他地方,您有对同一对象的引用。如果像现在一样通过重新分配变量来更改后一个引用,则不会更改字段最初引用的对象。这只是更改了本地后一个引用。
0赞 Pac0 3/20/2019
我真的不知道如何处理这样一个事实,即您以某种方式对参数有两个引用:一个在“参数”字段中,另一个在列表中的某个地方。这真的有必要吗?
0赞 Ignacio 3/20/2019
问题是,有一个 MainClass 包含许多 MyObject(比示例更复杂,包含更多内容)和几个共享对象的其他类(SecondaryClass、SecondaryClass2 等)。如果我在一个对象 SecondaryClass 中更改其中一个 myObjects 的值,我希望该更改传播到 MainClass、SecondaryClass2 等其他对象。
0赞 Pac0 3/20/2019
嗯,正如你所看到的,这很复杂。也许这超出了 Stack Overflow 问题应该是什么样子的范围。也许最好的办法是解释你想要实现的目标,你的最终目标。这对我来说像是一个 XY 问题。也许您的整体架构可以改进和简化很多,但我们需要知道您的规格,您想要实现什么。
1赞 parttimeadjunct 3/21/2019 #3

您是否尝试过将 MyObject 类设置为单例?然后,您可以使用任何数据结构类,例如 HashTable。我建议使用 Hashtable 的原因是因为它是线程安全的。