使用ref关键字表示参数将被修改。

4
我知道ref的意思是,当方法返回时,引用所指向的对象可能完全不同。
然而,我喜欢ref修饰符的原因在于,开发人员可以立即了解到他所输入的内容在方法返回时可能会有所不同,因为调用方也需要使用ref修饰符。
接下来是一个来自一个假想ORM的简单方法:
public Boolean AddItem(Entity someEntity)
{
  try
  {
    // Add item to database
    // Get Id of entity back from database
    someEntity.Id = *returnedId*;
    return true;
  }
  catch (DBException ex)
  {
    return false;
  }
}

任何调用该方法的人都可能不知道他们的实体是通过调用该方法更新的。然而,将someEntity作为ref参数,这表明开发人员提交的参数将是不同的,他们就知道要查看文档/代码以查找它如何更改,如果没有这个修饰符,他们可能从未想过这样做。
我知道这有点滥用ref修饰符,因为在上面的示例中实际上并不需要它,但是这样使用会给我带来任何问题吗?

1
通过声明成员为公共,您决定它们可以被任何具有对您对象的引用的外部对象访问和/或修改。如果不应该被修改,它应该是私有的。 - Tobsey
我相信如果 AddItem 的作者想要告诉调用者 嘿,我不会修改参数,他会使用结构体作为参数。在 C++ 中,有一个 const 修饰符可以确保参数不会被修改。为什么在 C# 中没有这个修饰符呢?这里有一个很好的解释:https://dev59.com/KXA75IYBdhLWcg3wf5NV - user2160375
3
这里没有要审查的代码。楼主在询问一个概念。同时,我们不会审查假设性的代码。不要通过,也不要收取200美元。 - Dan
5
我认为这是一个糟糕的想法。现在在调用这种方法之后,我需要检查我的非空引用是否突然变成了空引用。在我看来,解决这个问题的正确方法是使用不可变类型和/或正确的方法文档。 - Matthew Watson
不,不,不,不,不不不!糟糕的开发者。淘气!这只是说我可能在方法中放置了一个可怕的副作用,你应该处理它,因为我懒得去管它。 - Tony Hopkinson
显示剩余7条评论
2个回答

6
我认为这是滥用。假设Entity是一个引用类型,参数声明的方式可能会导致问题。
bool AddItem(ref Entity someEntity)

该方法可能会将引用someEntity移动到完全不同的对象实例上。

如果您只是对现有实例someEntity进行变异,则不要写ref。而应使用名称(方法名称和参数名称)和说明文件,以明确表示您将“变异”(更改)对象。 示例名称(您可以选择更好的名称,因为您知道实际的代码):AddItemAndUpdateEntityID

使用ref的后果:

  • 调用者必须使用变量。他不能使用属性、方法调用或表达式评估的返回值。
  • 调用者必须使用确切的类型,他不能传递一个SpecificEntity,比如说,其中SpecificEntity派生自Entity
  • 您的方法的逻辑必须准备好,其他线程(或您自己调用的其他方法)可能会更改ref参数的标识。例如,如果在方法的开头检查someEntity == null,则在稍后的时间点中,可能已经发生了更改,因为其他人可能已经将引用移动到其他位置。

我之前并不知道这些后果,太棒了,这正是我在寻找的答案。命名/注释就是关键! - Lee

4
然而,我喜欢ref修饰符的原因是开发人员可以立即知道他放入的内容在方法返回时可能会有所不同,但他们并不知道这一点。他们了解ref修饰符的信息是,当方法返回时,参数实际上可能指向其他东西。将接受引用类型的方法改为仅使用ref,以便提供错误印象是没有任何用处的。当然,反过来也有一个问题;除了滥用ref表示它不意味着的东西外,你已经失去了ref指示它意味着什么的能力;一个人必须检查代码才能确定方法实际上是否使用了ref,并且从一个方法调用到另一个方法调用,您无法确定自己是否仍在处理相同的对象。

我猜对于不熟悉非传统编码风格的人来说可能会有些困惑,感谢你的回答。 - Lee
1
对于熟悉它的人来说,这可能会令人困惑;他们仍然无法确定一个方法是否真正使用了 ref - Jon Hanna
同意,我很少(如果有的话?)找到使用ref提供的功能的理由,它似乎被浪费了!即使每个人都熟悉,并被告知在注释中查找ref的正确用法(疯狂,我知道),出于Jepp解释的原因,这也不是一个可行的选项,我将继续使用命名/注释。 - Lee
我希望你很少使用 finalisers、显式垃圾回收、stackalloc 或其他很有用但只在需要时才需要的东西。 - Jon Hanna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接