默认使用ref关键字传递引用类型

时间:2009-09-22 07:40:02

标签: c#

我与默认使用ref关键字传递StringBuilder,string和MemoryStream等引用类型的开发人员合作。他们这样做无论他们是否需要实际更改引用本身。

public void ExampleMethod(ref MemoryStream ms)
{
    byte b=ms.ReadByte();
    ...
    // No changing of actual ms reference such as: ms=new MemoryStream();
}  

几乎总是,方法只使用对象并返回而不以任何方式更改引用。对于不可变类型即字符串,这有时是必要的,但为什么对于可变类型?

对我而言,这有一点“代码味道”,因为它可能会导致可维护性较低的代码,因为它比实际需要的更宽松。

然而,对于我来说,这对于培养开发人员来说是否足够严重?我的初衷是肯定的,但也许这太迂腐了?

5 个答案:

答案 0 :(得分:17)

也许你可以问开发者为什么这样做...... 也许他(错误地)认为它更有效率?也许开发人员是C ++开发人员,谁认为使用ref类似于在C ++中使用指针?

如果他来自C ++背景,我会问开发人员为什么这样做,并向他解释这完全没有必要。它不会提高性能,而是为方法提供不同的语义,因为它允许更改引用,并且只有在方法确实需要更改引用时才应使用ref关键字。

我认为这不是迂腐。即使是经验丰富的开发人员也不知道他正在使用的新语言的所有内容。当你向他解释时,他会学到新的东西,也许他会感激不尽。 :)

答案 1 :(得分:6)

绝对值得一提。我已经多次看到这种情况,而且一直是由于开发人员不了解类型系统 - 这是编写正确和可维护代码的关键部分。

我会找到一个显然没有必要的例子,但是他们想要改变对象本身的内容 - 附加到StringBuilder的东西是理想的。然后礼貌地问他们为什么选择使用ref修饰符。指出它在没有它的情况下也能正常工作。

随时将他们推荐给我的parameters article和我的reference/value type article

答案 2 :(得分:4)

我不认为它太迂腐,因为开发人员可能误解了“ref”关键字的优点。它应该在绝对必要的地方使用,表明该方法将保证或最有可能将您的引用与其他内容交换 - 而不是“只是为了好玩”。

更新
至于如何沟通......嗯,可能在一定程度上取决于他为什么要对所有事情进行反思的动机。如果他认为它会提高性能,那么使用 StopWatch.StartNew()进行一些程序,并将事物传递给带有和不带 ref 的方法。我没有尝试过,但会认为性能差异可能在于创建一个新的引用,而且应该很小。

除了应该按照预期使用功能并表达意图。当我看到一个带有 ref out 参数的方法时,我希望它们要么完全改变传入的实例,要么分别初始化传入的对象。不将这些关键字用于这些目的只是一种混淆其他程序员的方法,通过使用不必要的关键字混淆方法调用,并可能对所使用的API设置错误的期望。

答案 3 :(得分:3)

这看起来像是一种误解;需要ref关键字来传递对方法的引用。如果是这种情况,您应该询问开发人员。

在不需要时使用ref关键字的唯一理由是允许稍后更改方法以替换该对象。这应该仅用于您真正预期需要它的地方。通常,您应该只编写当前需求的代码,而不是您可以想象的每个可能的需求。

如果您发现因任何原因不需要的ref,则应将其从代码中删除。遵循封装原则,不应该为参数值赋予超出其需要的功率。

通常,很少会使用ref关键字。在大多数情况下,可以使用更面向对象的方法。出于性能原因,它有时会与值类型一起使用,例如在Double.TryParse方法中,但从未真正使用引用类型。

答案 4 :(得分:-1)

ref关键字仅在修改值类型(来自ValueType的任何内容)时有用。值类型包括intbytecharstructfloat等。使用ref作为对象引用或类,例如Stream后代或StringBuilder没有意义,绝对是代码气味。

我认为有必要将StringBuilder引用传递为ref的唯一一次是在Win32上编组字符串值时。