【问题标题】:How do I pass a const reference in C#?如何在 C# 中传递 const 引用?
【发布时间】:2009-09-06 08:40:15
【问题描述】:

在 C++ 中,传递 const 引用是一种常见的做法 - 例如:

#include <iostream>
using namespace std;

class X
{
  public :
    X()                              {m_x = 0; }
    X(const int & x)                 {m_x = x; }
    X(const X & other)               { *this = other; }
    X & operator = (const X & other) { m_x = other.m_x; return *this; }
    void print()                     { cout << m_x << endl; }
  private :
    int m_x;
};

void main()
{
    X x1(5);
    X x2(4);
    X x3(x2);
    x2 = x1;
    x1.print();
    x2.print();
    x3.print();
}

这个非常简单的示例说明了它是如何完成的 - 差不多。但是我注意到在 C# 中似乎并非如此。我必须在 C# 中传递 const 引用吗?我需要“ref”关键字做什么?请注意,我知道并理解 C# 引用和值类型是什么。

【问题讨论】:

  • 由于您是在用 C++ 术语思考,因此将 ref 关键字视为指针的最佳方式可能是。如果将它与值类型一起使用,那么它是一个单指针,对于 ref 类型,它是一个指向指针的指针。
  • Eric Lipperts 博客是这类事情的一个很好的参考。特别是他的“参考不是地址”条目。 blogs.msdn.com/ericlippert/archive/2009/02/17/…
  • @MartinHarris 我已经阅读了Jon Skeet's blog post on the matter 并且找不到任何反对您评论的内容。感谢您指出相似之处。多亏了这条评论,我相信我已经更好地学习了 c++ 和 c# 中的概念。

标签: c# reference constants


【解决方案1】:

回答您问题的参考部分;当您将变量传递给方法时,会创建该变量的副本。使用 ref 关键字将传递该变量的相同实例,以便该方法能够为调用者更新该变量。

很多人似乎认为这仅适用于值类型,因为引用类型只是作为引用传递,所以 ref 关键字不起作用。但是,这不是真的,reference 以与值相同的方式传递给方法;它被复制并创建了该 reference 的新实例。这意味着调用者将看到对对象本身的修改,而不是对引用的修改。因此,如果您尝试将对象设置为 null 或新对象,如果不使用 ref 关键字,调用者将不会看到此修改:

没有参考:

void UpdatePerson(Person person)
{
   // Caller would see this change
   person.Name = "Bob";
   // Caller wouldn't see this change
   person = null;
}

带参考

void UpdatePerson(ref Person person)
{
   // Caller would see this change
   person.Name = "Bob";
   // Caller would see this change
   person = null;
}

【讨论】:

  • 来自C++,第一个例子Without Ref很奇怪!因此,作为参数传递的Person 对象被复制到UpdatePerson(Person) 内部的本地Person 对象,并且允许对参数的字段成员进行修改,就像通过引用传递参数一样,但对本地对象的修改不会影响参数对象?
  • @MinhTran 为什么在 C++ 中很奇怪? person 是按值传递的,所以它完全取决于复制构造函数是如何定义的。例如,如果成员变量namestd::string 类型,则编译器生成的复制构造函数的行为将与此处的C# 完全相同。
【解决方案2】:

C# 没有 const 对象的概念(即不能修改的对象);只有变量(即字段)可以是 const 或 readonly - 这意味着您不能分配给它们。

ref 关键字在概念上传递对变量的引用作为参数,即被调用者可以修改变量(而不仅仅是修改值)。这对于原始类型(int、bool 等)特别有用。

【讨论】:

  • 其实 int 在严格意义上并不是不可变的,因为它可以在创建后修改(而不可变对象在创建后不能更改)。 int 和其他原始类型的问题在于它们是按值传递的,因此您实际上可以在函数中更改它们,但是您将更改它们的副本,而不是它们本身。所以我宁愿写“不可变类型和原始类型”。
  • 好的,我不再提到不可变了。
  • 如何修改 int?赋值不算数(您也可以通过分配新引用来“修改”不可变引用类型)。 int 既是值类型又是不可变的。实际上,对于不可变类型,您无法真正区分引用类型和值类型(使用 ReferenceEquals 除外)。只有当类型是可变的(具有属性设置器或变异方法)时,引用和值之间的差异才开始发挥作用。 .NET 中的大多数值类型都是不可变的(所有原始类型、DateTime、TimeSpan 等)
【解决方案3】:

从 C# 7.2 开始,这是可能的using the in keyword

【讨论】:

  • 不错的选择。谢谢。
【解决方案4】:
猜你喜欢
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多