为什么数据集通过引用传递而没有显式传递或ref参数

本文关键字:参数 ref 数据集 引用 为什么 | 更新日期: 2023-09-27 18:02:32

我看不懂这段代码,这里对DataSet对象和字符串变量的实现相同,但输出不同。我可以看到字符串变量输出背后的逻辑,但对于数据集,我不明白为什么!

class Program
    {
        static void Main(string[] args)
        {
            DataSet ds = new DataSet();
            FillDS(ds);
            PrintDS(ds);
            string name = "old";
            AssignString(name);
            PrintString(name);
        }
        private static void AssignString(string name)
        {
            name = "new name";
        }
        private static void PrintString(string name)
        {
            Console.WriteLine(name);
        }
        private static void FillDS(DataSet ds)
        {
            ds.Tables.Add(new DataTable("tbl1"));
            ds.Tables.Add(new DataTable("tbl2"));
        }
        private static void PrintDS(DataSet ds)
        {
            foreach (DataTable item in ds.Tables)
            {
                Console.WriteLine(item.TableName);
            }
        }
    }
//Output:
//tbl1
//tbl2
//old

为什么数据集通过引用传递而没有显式传递或ref参数

字符串是不可变的,加上你没有修改字符串参数(不是你可以),而是你分配一个新的引用给你的参数。原来的仍在原地。

对于DataSet,您正在修改其内容,并且由于它是一个可变引用类型,因此您可以在调用方中看到更改。

Main

中尝试以下操作
    DataSet ds = new DataSet();
    ds.Tables.Add(new DataTable("tbl3"));
    FillDS(ds);

,然后在FillDS中给DataSet分配一个新的引用,如:

private static void FillDS(DataSet ds)
{
    ds = new DataSet(); //Here 
    ds.Tables.Add(new DataTable("tbl1"));
    ds.Tables.Add(new DataTable("tbl2"));
}

你会看到你的DataSet仍然保持旧的值,并且在调用FillDS

之后没有任何修改

stringDataSet都是引用类型。所以在这两种情况下都传递引用。

AssignString方法中,您不更改传递的string实例,但将新实例 ("new name")分配给变量namename变量实际上是一个参数这一事实并不重要(尽管重新分配参数被认为是一种不好的做法)。

FillDS中,不是重新分配一个新实例,而是通过ds.Tables....访问和操作传递的实例的属性。

因为DataSetstring都是引用类型,并且在引用类型中,它总是传递对象在托管堆上的内存地址。