C# 为什么通过引用传递数据集而不显式传递或引用参数?
我无法理解这段代码,这里的DataSet对象和string变量实现相同,但输出不同。我可以看到string变量输出背后的逻辑,但对于DataSet,我无法理解为什么C# 为什么通过引用传递数据集而不显式传递或引用参数?,c#,C#,我无法理解这段代码,这里的DataSet对象和string变量实现相同,但输出不同。我可以看到string变量输出背后的逻辑,但对于DataSet,我无法理解为什么 class Program { static void Main(string[] args) { DataSet ds = new DataSet(); FillDS(ds); PrintDS(ds);
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
因为
数据集
和字符串
都是引用类型,而在引用类型中,它始终是对象在托管堆上所在位置传递的内存地址。字符串是不可变的,而且您没有修改字符串参数(不是您可以修改的),但是,您将为参数指定一个新的引用。原作仍在原处
使用DataSet
,您正在修改它的内容,因为它是一种可变的引用类型,所以您可以在调用者中看到更改
在Main
DataSet ds = new DataSet();
ds.Tables.Add(new DataTable("tbl3"));
FillDS(ds);
然后在FillDS
中为您的数据集指定一个新引用,如:
private static void FillDS(DataSet ds)
{
ds = new DataSet(); //Here
ds.Tables.Add(new DataTable("tbl1"));
ds.Tables.Add(new DataTable("tbl2"));
}
您将看到,您的数据集
仍然保留旧值,并且在调用FillDS
后,不会修改任何内容字符串
和数据集
都是引用类型。因此,在这两种情况下,您都会传递引用
在AssignString
方法中,您不会更改传递的string
实例,而是将一个新实例(“new name”
)分配给变量name
。name
变量实际上是一个参数这一事实并不重要(尽管重新分配参数被认为是一种不好的做法)
在FillDS
中,您不会重新分配新实例,而是通过ds访问和操作传递的实例的属性。表..
字符串也是引用类型。感谢@Habib的指点,我错过了“相同实现”这个比特,你是什么意思?在AssignString
中,您正在为name
参数指定一个新值。在FillDS
中,您没有为ds
参数分配任何内容。您正在对其调用更改其内容的方法。你能看出这两个动作是不一样的吗?如果在FillDS
中指定了ds=new DataSet()
,您会发现作为参数传入的数据集不会发生更改。我可能不会为传递给AssignString的参数指定新值,我可能会这样做:name.Remove(0,1);输出:old它们都是引用类型,为什么字符串不从原始数据中获取副本,而是从数据集获取副本?顺便说一句,如果我用intRead替换字符串,结果仍然相同。它不改变字符串,只返回一个新字符串。碰巧字符串没有改变它的方法;它们只返回不同的新字符串。请在Main
函数中尝试此代码:var s=“test”;s、 移除(0,1);控制台。写入线(s)代码>。您将发现String.Remove()
从不更改字符串。然后试试这个:var s2=s.Remove(0,1);控制台写入线(s2)
您会发现String.Remove()
返回的字符串与原始字符串不同。但是它不会更改原始属性。string
类型中是否有与本例中的DataSet
相同的属性?@MohamedAhmed No.string
被设计为不可变的。对字符串
实例的每一个可能操作都会返回一个值已更改的新实例,但不会更改当前实例。C#中是否有可变和不可变类型的主题/主题?我想我以前没有接触过这个话题,因为我发现int
type的行为与string
在这个例子中,如何判断一个类型是可变的还是不可变的?@MohamedAhmed这是一个开始,正如我所说,谷歌是你的朋友……我从第二个搜索结果开始:我如何判断一个类型是可变的还是不可变的?我发现int
也是不可变的!文件。。。看到Eric Lippert的作品了吗