在C#

时间:2019-03-20 13:06:01

标签: c# .net pass-by-reference

如果两个类具有相同的键(只是一个字符串),我想让两个类共享一个对象,因此,如果对象的值更改,则这两个类都会更改。我认为这就像使两个对象指向相同的内存地址一样,因此在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对象)。

3 个答案:

答案 0 :(得分:2)

使用parameter = newParameter,您只修改了MyObject parameter的引用,它是一个局部变量。 您没有在secondaryClass列表中修改对象的引用。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

问题的原因由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的内部字段,这将大大简化代码的访问和可读性。

相关问题