在 C# 中的类之间共享对象
Posted
技术标签:
【中文标题】在 C# 中的类之间共享对象【英文标题】:Share objects between classes in C# 【发布时间】:2019-08-11 04:30:28 【问题描述】:如果两个类具有相同的键(它只是一个字符串),我希望它们共享一个对象,因此如果对象的值发生变化,它会在两个类中发生变化。我认为这就像让两个对象指向相同的内存地址一样,所以在 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# 中对象的 reference。var a = new Something(); var b = a; // now b refers to the *exact same object as a* in memory
(如果 Something
是一个类)。顺便说一句,类也被称为引用类型,原因相同。
@Pac0 是的,我预料到了,但事实并非如此。
很难准确理解您要查找的内容,因为您只发布了伪代码。请提供minimal reproducible example。
使用字典太容易了。
@JonSkeet 完成了,下次我会从头开始这样做
【参考方案1】:
使用parameter = newParameter
,您只需修改MyObject parameter
的引用,这是一个局部变量。
您没有在 secondaryClass 列表中修改对象的引用。
【讨论】:
这正是造成混乱的原因。【参考方案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);
注意:我不理解使用参数“列表”以及使用字段存储单个参数的想法。
按照建议,如果您有多个键值对,则应使用 Dictionary<string, MyObject>
作为 MainClass 和 SecondaryClass 的内部字段,这将大大简化代码的访问和可读性。
【讨论】:
那只会更新值,而不是对象本身。我已经包含了新代码,可以看出在最后几行中我希望两个对象是相同的。 @Ignacio :您必须创建一些代码来执行更新,例如 SecondaryClass 的方法。为了更好地理解:您有一个引用对象的字段。在其他地方,您有对同一对象的引用。如果您通过重新分配变量来更改后一个引用,就像您所做的那样,这不会更改该字段最初引用的对象。这只是更改本地后一个引用。 我真的不知道如何处理您以某种方式对参数有两个引用的事实:一个在“参数”字段中,另一个在您的列表中。真的有必要吗? 问题是有一个 MainClass 有许多 MyObject(比示例更复杂,有更多东西)和其他几个共享对象的类(SecondaryClass、SecondaryClass2 等)。如果我更改一个对象 SecondaryClass 中的 myObjects 之一的值,我希望该更改传播到 MainClass、SecondaryClass2 等的其他对象。 嗯,这很复杂,如您所见。也许这超出了堆栈溢出问题的范围。也许最好的方法是解释你想要达到的目标,你的最终目标。这对我来说就像XY problem。也许你的整体架构可以改进和简化很多,但我们需要知道你的规格,你想要实现什么。【参考方案3】:您是否尝试过将 MyObject 类设为单例?然后您可以使用任何数据结构类,例如 HashTable。我建议使用 Hashtable 的原因是因为它是线程安全的。
【讨论】:
以上是关于在 C# 中的类之间共享对象的主要内容,如果未能解决你的问题,请参考以下文章