与 C++ 相比使用 C# 'ref' 关键字

Use of C# 'ref' keyword compared to C++

本文关键字:ref 关键字 C++      更新时间:2023-10-16

我主要在C++工作,现在我在新工作中使用 C#,在这里阅读了一些关于"ref"关键字和 c# 值与引用类型的内容后,我仍然发现它们有些混淆。

据我了解,如果您将这些传递给一种方法,这些将类似于C++样式:

值类型:

public void CSharpFunc(value)

public void CPlusplusFunc(value)

参考类型:

public void CSharpFunc(reference)

public void CPlusPlusFunc(&reference)

"引用"/指针

public void CSharpFunc(ref bar)

public void CPlusPlus(*bar)

这是一个正确的类比吗?

这是一个正确的类比吗?

不管其他答案怎么说,没有。ref在C++方面的含义实际上取决于类型。对于值类型,您的评估是正确的(或足够接近)。对于引用类型,更合适的类比是引用指针:

public void CPlusPlus(type*& bar)

关于ref的全部意义在于您可以更改传入的引用。而且你不能通过简单地传递一个指针来做到这一点C++:

void f(type* bar) {
    bar = new_address;
}
type* x;
f(x);

此代码不会更改调用方的值 x 。另一方面,如果您将bar作为 type*& 传递,它会更改值。这就是ref所做的。

此外,C# 中的引用与 C++ 中的引用完全不同,更像是 C++ 中的指针(因为您可以更改引用引用的对象)。

交换

"引用类型"和"ref"示例会更准确(尽管仍然不完全相同)。

在 C# 中,引用类型是始终通过对该类型的实例的引用在内部访问的类型。从C++意义上讲,最简单的方法是将这些作为"指针":分配内存,运行构造函数,并返回间接引用所需对象的值。C# 和此处C++之间的区别在于,在 C# 中,这是类型的属性,而不是变量的属性。类型要么始终是引用类型,要么始终是值类型。这样做的一个效果是,无需执行任何特殊操作即可使用引用类型(托管 C# 代码中没有"取消引用"运算符);编译器假定引用类型变量访问是定向的。在C++中,您仍然需要使用 -> 运算符,因为您可以同时拥有相同类型的值变量和引用变量(object x vs. object *x )。

ref 关键字用于通过引用传递参数;这些参数可以是值类型(如 int)或引用类型。虽然 ref 关键字的实现最终是地址/指针类型操作(与&中的C++完全相同),但ref(和out)生成一种称为托管引用的特殊类型的对象,它与引用类型不同,因为您可以对值类型进行托管引用。这几乎正是C++的工作方式:int&是一种特殊类型的"对 int 的引用",与 int * 不同,即使两者都基本上使用指针间接寻址来访问变量。同样,在C#中你可以有一个ref Object,这实际上是一个object *&

是的,你基本上是正确的,(s/*/*&你在那里100%)。 正如@weston提到的,out是一个需要熟悉的附加关键字。 你可以用ref做的唯一可爱的事情是重载一个不是 ref 的函数。

class Person {
   string Name { get; set; }
   string Address { get; set; }
   int age { get; set; }
}
public void UpdateName(Person p)
{
   if (p == null) 
   {
      return;
   }
   p.Name = "Tom";
}
public void UpdateName(ref Person p)
{
   if (p == null)
   {
      p = new Person();
   }
   p.Name = "Tom";
}

显然没用,但它确实提供了一些有趣的机会(和糟糕的设计)。 out不提供相同的重载功能。

如果你想要 1 对 1,你总是可以用 unsafe 阻止你的代码。