【问题标题】:different by ref question using a simple =不同的参考问题使用一个简单的=
【发布时间】:2010-11-05 05:24:31
【问题描述】:

我对 by ref 问题有一个变体。我知道所有关于使用 ref 或我们的参数调用以及它如何影响变量及其值的知识。我在使用 DataTable 时遇到了这个问题,我想知道为什么数据表不同于简单的整数变量。

我有关于如何解决问题的实际答案,但我想知道它为什么会这样工作。

如果你使用简单的变量,它会达到我的预期

        int mVar1 = 1;
        int mVar2 =1;

        mVar2 = mVar1;

        mVar2 = 5;

        Console.WriteLine(mVar1.ToString());
        Console.WriteLine(mVar2.ToString());

它显示 1,5 在控制台中。

但是如果你对 DataTable 做同样的事情,它会引用第一个数据表而不是新值:

        DataTable mVar3 = new DataTable();
        DataTable mVar4 = new DataTable();


         // Create DataColumn objects of data types.
        DataColumn colString = new DataColumn("StringCol");
        colString.DataType = System.Type.GetType("System.String");
        mVar3.Columns.Add(colString);

        // Create DataColumn objects of data types.
        DataColumn colString2 = new DataColumn("StringCol123");
        colString2.DataType = System.Type.GetType("System.String");
        mVar4.Columns.Add(colString2);

        foreach (DataColumn tCol in mVar3.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }
        foreach (DataColumn tCol in mVar4.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }

                mVar4 = mVar3;

        //change mVar4 somehow and see if mVar3 changes


        foreach (DataColumn tCol in mVar4.Columns)
        {
            tCol.ColumnName = "Test";

        }

        foreach (DataColumn tCol in mVar3.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }

        foreach (DataColumn tCol in mVar4.Columns)
        {
            Console.WriteLine(tCol.ColumnName);

        }

控制台显示: 字符串科尔 字符串Col123 测试 测试

通过说 mVar4 = mVar3 会导致 mVar4 成为对 mVar3 的引用。

这个问题的解决办法就是说

DataTable mVar4 = mVar3.Copy(); 

所以我的问题是:是什么导致数据表的执行与简单的整数字段不同。为什么当我使用 mVar4 = mVar3 而不是 DataTable 的不同副本时它会创建引用?

【问题讨论】:

    标签: c# reference datatable pass-by-reference byref


    【解决方案1】:

    您遇到了引用类型和值类型之间的差异。

    这是关于差异的msdn article

    一个更具描述性的答案是两者实际上都在执行相同的操作,不同之处在于在第一个示例(两个整数)中,mVar2 = mVar1 的赋值是将 mVar1 的值分配给 mVar2,即 1。但是,在 DataTable 的情况下,实际分配的是内存位置,而不是 DataTable。

    例如,假设您创建的 DataTable 位于内存位置 20。这意味着引用 mVar1 将持有对该位置 (20) 的引用。当您执行分配 mVar2 = mVar1 时,您是在告诉 mVar2 保持与 mVar1 相同的值,因此 mVar2 也会引用内存位置 20。结果是两个变量都引用了同一个DataTable。

    如您所说,为了实现您所描述的行为,您确实需要具备复制能力。它必须分配一个全新的对象,并将前一个对象的状态复制到新对象。

    对于 DataTable 类,您可以在扩展方法中像这样扩展它:

    public static DataTable Copy(this DatTable original)
    {
       var result = new DataTable();
       //assume Property1 was a property of a DataTable
       result.Property1 = original.Property1; 
       //continue copying state from original to result
       return result;
    }
    

    【讨论】:

    • 我喜欢 MSDN 文章,因为它解释了某物是什么类型。现在我看到,当我将鼠标悬停在 Visual Studio 中的 DataTable 数据类型上时,它显示类 DataTable,根据 MSDN 文章,它是参考类型。感谢您提供此信息,它解释了一切!请注意,数据表已经有一个复制方法。
    【解决方案2】:

    调用 mVar2 = mVar1;复制存储在 mVar1 位置的值。在这种情况下,这意味着 1 被复制到位置 mVar2 中。在第二种情况下,存储在 mVar3 中的值再次被复制到 mVar4 的位置。但是,在这种情况下,因为 DataTable 是引用类型,所以复制的值是对实际 DataTable 对象的引用。

    为了进一步展示这一点,请将以下内容添加到您发布的代码的末尾:

            mVar4 = new DataTable();
            // Create DataColumn objects of data types.
            DataColumn colString3 = new DataColumn("StringCol1234");
            colString2.DataType = System.Type.GetType("System.String");
            mVar4.Columns.Add(colString3);
    
            foreach (DataColumn tCol in mVar3.Columns)
            {
                Console.WriteLine(tCol.ColumnName); // still outputs test
    
            }
    
            foreach (DataColumn tCol in mVar4.Columns)
            {
                Console.WriteLine(tCol.ColumnName); // now outputs StringCol1234
    
            }
    

    如果您再次将 mVar4 设置为 DataTable 的新实例,则所做的更改不会反映在 mVar3 中。这是因为调用 mVar4 = new DataTable();改变了 mVar4 位置的引用,不会改变 mVar4 引用的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 2011-02-18
      • 2012-06-06
      • 2016-04-23
      • 2023-03-09
      • 1970-01-01
      相关资源
      最近更新 更多