10

我主要在 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)

这是一个正确的类比吗?

4

3 回答 3

12

这是一个正确的类比吗?

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

public void CPlusPlus(type*& bar)

重点ref是您可以更改传入的引用。而在 C++ 中,您不能通过简单地传递一个指针来做到这一点:

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

type* x;
f(x);

此代码不会更改调用方的x. 另一方面,如果你传递了baras ,它就会改变值。就是这样。type*&ref

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

于 2012-08-13T13:39:02.927 回答
3

交换“参考类型”和“ ”示例会更准确(尽管仍然不完全相同)。ref

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

ref关键字用于通过引用传递参数;这些参数可以是值类型(如int)或引用类型。虽然ref关键字的实现最终是一个地址/指针类型操作(就像&在 C++ 中一样),但ref(and out) 会产生一种特殊类型的对象,称为托管引用,它不同于引用类型,因为您可以有对值类型的托管引用。这几乎正​​是 C++ 的工作方式:anint&是一种特殊类型的“对 int 的引用”,与 不同int *,尽管两者基本上都使用指针间接访问变量。同样,在 C# 中,您可以拥有一个ref Object,这实际上是一个object *&.

于 2012-08-13T13:39:37.650 回答
1

是的,你基本上是正确的,(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.

于 2012-08-13T13:34:01.540 回答