【问题标题】:C# pointer issueC#指针问题
【发布时间】:2011-11-28 21:31:51
【问题描述】:

看看下面的例子:

public void inc(int num) {
   num++;
}

int a = 5;
inc(a);

在这种情况下,inc 不会增加 a 变量本身。它没有指向内存中的相同位置。为了更改a,我必须使用ref

然而,在这个例子中

public static void ExportSelectedRow(GridView gridView, object toObject, int skipCols)
{
    GridViewRow gridViewRow = gridView.SelectedRow;

    if (toObject is DataTable)
    {
        DataTable returnDt = (DataTable)toObject;
        GridViewColsToDatatable(gridView, returnDt, skipCols);
        DataRow dr = returnDt.NewRow();
        for (int i = skipCols; i < gridViewRow.Cells.Count; i++)
            dr[i - skipCols] = gridViewRow.Cells[i].Text;
        returnDt.Rows.Add(dr);
    }

}

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e) {
    DataTable dt = new DataTable();
    GridViewHelper.ExportSelectedRow(GridView1, dt, 1);
    ...
}

选定的行将从GridView1 导出到DataTable,尽管我什至没有在函数中引用它。所以toObject 将被更新。看来

DataTable returnDt = (DataTable)toObject;

实际上是在引用toObject。所以我的问题是,为什么在这个例子中它是一个参考,但在第一个例子中,它不是?

【问题讨论】:

  • 请注意,'ref' 参数值实际上是对字段、局部变量或数组元素的类型化引用——它不是指针。可以将其视为“对被调用代码中变量的更改应该导致对调用代码中变量的更改”。它是从引用发生方式的底层实现中抽象出来的,它比指针受到更严格的约束(它可能引用内存中的任何地方,而类型化引用受到高度限制。)

标签: c# pointers reference


【解决方案1】:

与其他人所说的相反,默认情况下,C# 中的 所有内容(也是引用类型)是按值传递的。 refout 不是。
但是在引用类型的情况下,按值传递的东西是引用

int当然是值类型,DataTable是引用类型。

【讨论】:

  • 支持你,因为你是唯一一个绝对正确的人。其他,见mbaldinger.com/post/C-reference-types-are-passed-by-value!.aspx
  • 请注意,虽然这正确的,但我也认为初学者程序员很难理解。就像古典语言中的指针一样,这需要时间来“得到它”。因此,我也认为更详尽(或更简单)的解释也会很好。
  • @Vilx 是的,对引用(对对象)的引用的概念对于初学者来说绝对难以理解,尽管好的示例对此有所帮助。然而,我遇到了太多的非初学者,他们仍然对此感到困惑,所以从一开始就正确地教授它似乎更好,即使它很难掌握。
【解决方案2】:

C# 有参数类型。值类型(结构、枚举、数字等)和引用类型(对象、字符串等)。

在您的第一个示例中,值 5 被传递给函数,但在第二个示例中,GridView1 的引用被传递。

请参阅 MDN 以获取 value-typesreference-types 的列表,它们定义了如何传递参数。

编辑

要获得更好的定义,请参阅 harold 的回答。

【讨论】:

  • -1 是否内置与它无关,只有 ref 是严格(且有用)定义的传递引用。在没有ref 的情况下,复制值类型,而对于引用类型,仅复制引用。编辑:Downvote 被删除,因为编辑删除了明显错误的内容并添加了更准确的术语,尽管我仍然认为它可以更好地表达(对于初学者来说,什么是“简单类型”?)。
  • @Chad:值类型和引用类型是两种不同的数据类型(详见msdn.microsoft.com/en-us/library/t63sy5hs(v=vs.80).aspx)。还有不同类型的参数:refout 是两个例子。请注意,ref 可以应用于值类型参数或引用类型参数。这两个概念是独立的。请参阅@harold 的答案,这似乎是唯一正确区分这一点的答案。
【解决方案3】:

DataTable 是一个引用类型。 int 是一个值类型。

C# 按值传递(除非使用 refout)。

  • 当您将DataTable 传递给方法时,实际上是在传递引用 的副本。两个引用都指向同一个对象。对对象的修改将对调用者可见。
  • 当您传递 int 时,您传递的是 的副本。

如果您使用ref 关键字,它将改为通过引用传递。

【讨论】:

    【解决方案4】:

    .NET 中有两种类型的 ermm... 类型:值类型和引用类型。差异正是您在上面所展示的。

    基本上每个struct 都是值类型,每个class 都是引用类型。基本类型(如 int、decimal、datetime、byte 等)也实现为结构,因此它们是值类型。嗯,实际上,它们有点特别,但它们很像结构。

    MSDN 对此有一个article,该主题也已在其他地方广泛讨论。只需在 Google 上搜索“值类型与引用类型”即可。

    【讨论】:

      【解决方案5】:

      这里的区别在于基本类型(如 int 或 double)与对象之间。当你传递一个对象时,你传递的是对它的引用,而对于内部类型,你传递的是值的副本给函数。

      结构的有趣之处在于它们在语法上看起来像类,但通过值(复制)而不是通过引用传递。

      【讨论】:

        猜你喜欢
        • 2010-11-15
        • 2011-08-02
        • 2011-04-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多