使用ref来指示参数将被修改

时间:2015-04-09 08:53:32

标签: c# theory language-design

我理解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修饰符,因为在上面的示例中实际上并不需要它,但是这样使用它实际上会给我带来任何问题吗?

2 个答案:

答案 0 :(得分:4)

我认为这是滥用。假设Entity是引用类型,参数声明

bool AddItem(ref Entity someEntity)

表示该方法可能会将引用someEntity移动到“指向”完全不同的对象实例。

如果您只是 mutate 现有实例someEntity,请不要写ref。相反,使用名称(方法名称和参数名称)和文档清楚地表明您将“改变”(更改)对象。  示例名称(您可以选择更好的名称,因为您知道实际代码):AddItemAndUpdateEntityID

使用ref

的后果
  • 调用者必须使用变量。他不能使用属性,方法调用或表达式评估的返回值
  • 来电者必须使用确切的类型,他无法传递SpecificEntity,比如,SpecificEntity来自Entity
  • 您的方法的逻辑必须准备好其他线程(或您自己调用的其他方法)可能会更改ref参数的标识。例如,如果您检查方法顶部是否someEntity == null,方法稍后可能已更改,因为其他人可能已将引用移至其他位置。

答案 1 :(得分:4)

  

然而,我喜欢的ref修饰符是开发人员在方法返回时立即知道他放入的内容可能会有所不同

不,他们不会。

他们对ref修饰符的了解是,当方法返回时,参数实际上可能会引用 else

更改接受引用类型的方法仅使用ref以便您可以给出错误的印象,这无论如何都无用。

当然还有另一面;除了滥用ref来表明它并不意味着什么,你已经失去了ref表明做什么意味着什么的能力;我们必须检查代码以查看该方法是否实际使用ref并且不会从一个方法调用到另一个方法中知道您是否仍在处理同一个对象。