还有一些问题上已定义的"参考"和"推"的参数,但他们似乎喜欢糟糕的设计。是否有任何情况下你觉得ref是正确的解决方案吗?

好像你随时可以做别的事情就是吸尘器。有人能给我一个例子,这将是"最佳"问题的解决方案?

有帮助吗?

解决方案

在我看来, ref 很大程度上补偿的困难的声明新的实用程序类型以及难以"追踪的信息在"现有的信息,这些信息是事情C#已经采取了巨大的步骤,朝向解决,因为其起源通过皇宫、仿制药,并匿名类型。

因此,没有,我不认为有很多的清楚的情况下使用它了。我认为这是一个很大程度上遗留下来的如何的语言是最初设计的。

我认为,它仍然是有意义的(如上所述)的情况下,需要返回某种错误代码从一个函数,以及返回值,但是没有别的(这样一个更大的类型是不是真有道理的。) 如果我们这样做所有的地方在一个项目,我可能会定一些通用的包装类型的事-再加上错误代码,但是在任何给定的实例 refout 是确定。

其他提示

嗯, ref 通常用于特殊情况,但我不会将其称为冗余或C#的遗留功能。你会看到它(以及 out )在XNA中使用了很多。在XNA中, Matrix 是一个 struct ,它是一个相当庞大的(我相信64个字节),如果你使用 ref将它传递给函数通常是最好的避免复制64个字节,但只有4个或8个。专家C#功能?当然。不再使用或表示不好的设计?我不同意。

一个领域是使用小实用功能,例如:

void Swap<T>(ref T a, ref T b) { T tmp = a; a = b; b = tmp; }  

我在这里看不到任何“更清洁”的选择。当然,这不完全是架构级别。

P / Invoke是我唯一能想到你必须使用ref或out的地方的地方。在其他情况下,它们可以很方便,但就像你说的那样,通常还有另一种更清洁的方式。

什么如果你想 返回多个对象, 对一些未知的原因不是绑在一起变成一个单一的对象。

void GetXYZ( ref object x, ref object y, ref object z);

编辑: 迪沃 建议使用的参数将会更适合于此。我不得不承认,他有一点。我会离开这个答案在这里的作为,为了记录在案,这是一个inadaquate的解决方案。出王牌REF在这种情况。

我认为最好的用途是那些你经常看到的用途;你需要同时拥有一个价值和一个“成功指标”。这不是函数的例外。

ref 有用的一种设计模式是双向访问者。

假设您有一个 Storage 类,可用于加载或保存各种基元类型的值。它可以是 Load 模式或 Save 模式。它有一组称为 Transfer 的重载方法,下面是处理 int 值的示例。

public void Transfer(ref int value)
{
    if (Loading)
        value = ReadInt();
    else
        WriteInt(value);
}

其他基本类型会有类似的方法 - bool string 等。

然后在一个需要“转移”的类上,你会写一个这样的方法:

public void TransferViaStorage(Storage s)
{
    s.Transfer(ref _firstName);
    s.Transfer(ref _lastName);
    s.Transfer(ref _salary);
}

这个相同的方法可以从 Storage 加载字段,或者将字段保存到 Storage ,具体取决于 Storage 的模式对象在。

实际上,您只是列出了需要传输的所有字段,因此它非常接近声明性编程而非强制性。这意味着您不需要编写两个函数(一个用于读取,一个用于写入),并且假设我在这里使用的设计是依赖于顺序的,那么确定字段将始终被读取非常方便/以相同的顺序书写。

一般来说,当一个参数被标记为 ref 时,你不知道该方法是读取它还是写入它,这允许你设计访问者类,工作在两个方向之一,旨在以对称的方式调用(即访问方法不需要知道访问者类在哪个方向模式下操作)。

比较:属性+反思

为什么这样做而不是归因于字段并使用反射来自动实现 TransferViaStorage 的等价物?因为有时候反射很慢就会成为一个瓶颈(但总是要确定这一点 - 它几乎不是真的,并且属性更接近于声明性编程的理想)。

的实际用途是创建结构时。 C#中的结构是值类型,因此在按值传递时始终完全复制。如果需要通过引用传递它,例如出于性能原因或者因为函数需要对变量进行更改,则可以使用ref关键字。

我可以看到某人是否有一个包含100个值的结构(显然已经存在问题),您可能希望通过引用传递它以防止100个值复制。那个并返回那个大型结构并写入旧值可能会出现性能问题。

使用“ref”的明显原因关键字是指您希望通过引用传递变量的时间。例如,将System.Int32之类的值类型传递给方法并更改其实际值。更具体的用途可能是您想要交换两个变量。

public void Swap(ref int a, ref int b)
{
   ...
}

使用“out”的主要原因是keyword是从方法返回多个值。我个人更喜欢将值包装在专门的结构或类中,因为使用out参数会产生相当丑陋的代码。用“out”传递的参数 - 就像“参考”一样 - 通过引用传递。

public void DoMagic(out int a, out int b, out int c, out int d)
{
   ...
}

当您必须使用'ref'关键字时,有一个明显的例子。如果对象已定义但未在您打算调用的方法范围之外创建,并且您要调用的方法应该执行'new'来创建它,则必须使用 'REF'。例如 {object a;功能(a);} {功能(对象o){o =新对象; o.name =&quot; dummy&quot;;} 不会对 object'a'做任何事情,也不会在编译或运行时抱怨它。它不会做任何事情。 {object a; Funct(ref a);} {Funct(object ref o){o = new object(); o.name =&quot; dummy&quot;;} 将导致'a'成为名为&quot; dummy &quot;的新对象。但是如果'new'已经完成,则不需要ref(但如果提供的话,则有效)。 {object a = new object(); Funct(a);} {Funct(object o){o.name =&quot; dummy&quot;;}

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top