通过参考vs价值

时间:2019-05-18 11:35:07

标签: c# .net .net-core

我正在浏览.NET Core的MySQL连接器代码。

我看到了以下代码:

public async Task DeleteAsync
{
    var cmd = Db.Connection.CreateCommand() as MySqlCommand;
    cmd.CommandText = @"DELETE FROM `BlogPost` WHERE `Id` = @id;";
    BindId(cmd);
    await cmd.ExecuteNonQueryAsync();
}

private void BindId(MySqlCommand cmd)
{
    cmd.Parameters.Add(new MySqlParameter
    {
        ParameterName = "@id",
        DbType = DbType.Int32,
        Value = Id,
    });
}   

这不会导致方法调用

await cmd.ExecuteNonQueryAsync();

成为无参数?

完整代码已开启 https://mysql-net.github.io/MySqlConnector/tutorials/net-core-mvc/

3 个答案:

答案 0 :(得分:2)

您似乎对C#中传递的语义如何工作感到困惑。您可能已经听说,C#默认情况下始终按正确的值传递变量。但是,C#具有两种不同类型的变量:value typesreference types

如果MySqlCommand是一个值类型(结构),则假定将其复制到BindId方法中是正确的。但是,MySqlCommand是类,因此是引用类型。

当您将引用类型传递给方法时,C#为内存中的对象创建引用的副本。因此,BindId中的引用仍然引用内存中的同一MySqlCommand对象。

我希望这是有道理的。我建议阅读有关该主题的一些官方文档:

Passing Parameters

答案 1 :(得分:1)

它将 reference 传递给命令(因为它是 reference-type ,即对象)作为参数/参数,并且正在传递该引用按值,即参考的单独副本。但是:基本上就像复制指针一样:指针的任何副本仍指向同一位置,因此引用副本仍指向同一对象。该对象的任何更改都将对所有具有相同引用副本的使用者可见。

此处“按值”的唯一相关之处在于,如果BindId方法将新值分配给cmd ,则分配给另一个对象对呼叫者不可见-呼叫者仍然只知道原始命令对象。

答案 2 :(得分:0)

.Net具有2种基本类型。引用和值类型。

引用类型值本身驻留在堆中,但是当您将引用值传递给方法CLR创建副本时,指向堆自身位置的该值的引用驻留在堆栈中引用并传递该副本。但是,由于它是参考,因此仍指向原始值。

值类型值本身驻留在堆栈中,并且值类型没有引用。当您将值类型传递给方法时,CLR将创建该值的副本并将其传递。而且,如果您要使用该值进行某些操作,原始文件也不会损坏。摘自John Skeet的博客

假设我们已打印了有关国家列表和网站的页面,其中包含与已打印页面相同的信息。

信息将相同,但是两种媒体类型的行为方式不同。打印的页面具有值语义,网站具有参考语义。换句话说,打印页面的行为类似于值类型,而网站的行为类似于引用类型。页面直接包含信息。当您访问网页时,您使用URL进行访问-在我们的示例中,该URL类似于用于访问引用类型对象的引用。

这是我所见过的最好的解释链接。

Ref vs value types in .Net Jon Skeet