【问题标题】:Why is the `ref` keyword not mandatory here? [duplicate]为什么 `ref` 关键字在这里不是强制性的? [复制]
【发布时间】:2019-08-15 18:29:32
【问题描述】:

我显然不明白ref 和一个参数的范围不够好。有人能告诉我为什么这段代码有效吗?如何将dt 发送到函数中(我的意思是它将成为一个参数,并且作用域将是一个局部变量,对吧?)。那么为什么在调用fill() 之后dt 填充(填充)?

所以我的第一个想法是我只是用fill() 发送对dt 的引用,但后来我不理解ref 关键字。我认为这就是我们的目的.. 当参数是按类型的值时,您是否只需要使用ref

var dt = new DataTable();
using (var cmd = new MySqlCommand(cmdText, connection))
using (var adapter = new MySqlDataAdapter())
{
    adapter.SelectCommand = cmd;
    adapter.Fill(dt); // <---why is ref not needed here?
}
return dt;

【问题讨论】:

  • ref 在您更改引用时使用,而不是引用的实例。所以你可以在不使用ref的情况下修改引用的实例,但是当你想引用另一个对象时,你必须使用ref
  • DataTable 是引用类型,因此它已经通过引用传递。如果要精确:引用是按值传递的。添加另一个 ref 将通过引用传递引用,允许您更改 dt 引用的内容。间接!全家人的乐趣。
  • @HimBromBeere 是的,在说了一些错误、令人困惑和误导的话之后。这就像说,“橙色是紫色的,虽然如果你想准确地说它实际上是橙色”。继续纠正自己并不会使明显不正确的陈述更加正确,或者减少误导或混淆。
  • 正确的思考方式是不要认为ref 与“引用”有任何关系。想象一下,关键字不是ref,而是alias,它变得更加清晰。 ref 仅表示“此变量是引用变量的另一个名称”。当你说int x = 123; M(ref x); 时我们有void M(ref int y),这只是意味着y 是变量x 的另一个名称——它是一个别名
  • 为了更深入地了解参考和价值,我推荐 Lewis Carroll 的 Through thelooking-Glass,第 8 章。虽然我看到了 Servy 的观点,但我坚持我的评论,写成具有一定的解释价值,而实际上,它不是关于 C# 语义的正确和精确的陈述。幸运的是,这个问题有一个完整的答案。 (顺便说一句,“颜色”是那些美妙的准物理属性之一,你可以深入了解它实际上相对于我们幼稚的理解,所以这很贴切。)

标签: c#


【解决方案1】:

ref 在您更改引用时使用,而不是引用的实例。所以你可以不使用ref修改引用的实例,但是当你想引用另一个对象时,你必须使用ref

话虽如此,Fill 只会修改传递给它的内容,它不会创建新的DataTable

另一方面,当你想返回另一个实例时,你必须使用ref

void DoSomething(ref dt)
{
    dt = new DataTable();
    // do something with the new table
}

现在您有两个表,一个传递给DoSomething,另一个是在该方法中创建的,与前者没有任何任何共同之处。但是调用代码现在引用了那个新实例,原来的引用丢失了。

【讨论】:

  • 所以当我传递一个引用类型的对象时,我不需要使用ref,除非引用是在函数内新建的。
  • 你描述得更好,但我想我明白了。我从某种意义上说,对象是“新的”,所以我无法从头到尾知道引用。但是您何时或为什么想要/需要发送一些新的参数?在不总是这样的情况下,或类似的情况?
  • @radbyx ref-当您的方法确实返回多个内容时,参数可能很有用。虽然这也可以使用out-参数来实现,但ref 可以在覆盖引用之前由DoSomething 使用。所以你可以调用它的任何成员并之后引用另一个实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
  • 2023-01-16
  • 2015-04-08
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多