繁体   English   中英

返回引用与不返回任何内容之间的区别

[英]Difference between returning reference vs not returning anything

这两种方法有区别吗?

public class A
{
    public int Count { get; set; }
}

public A Increment(A instance)
{
    instance.Count++;
    return instance;
}

public void Increment(A instance)
{
    instance.Count++;
}

我的意思是,除了一个方法返回相同的引用而另一个方法没有返回任何东西,它们都完成相同的事情,增加作为参数传递的引用的Count属性。

使用一个对另一个有优势吗? 我通常倾向于使用前者,因为方法链接,但有性能权衡吗?

例如,后一种方法的一个优点是无法创建新的引用:

public void Increment(A instance)
{
    instance.Count++;
    instance = new A(); //This new object has local scope, the original reference is not modified
}

这可以被认为是针对接口的新实现的防御方法。

我不希望这是基于意见的,所以我明确地寻找从文档或语言规范中取出的具体优点(或缺点)。

例如,后一种方法的优点之一是不能创建新的引用。

你可以考虑其中一个缺点。 考虑:

public A Increment(A instance)
{
  return new A { Count = instance.Count +1 };
}

要么

public A Increment()
{
  return new A { Count = this.Count +1 };
}

一致地应用它,你可以让你的A类不可变,带来所有的优点。

它还允许返回实现相同接口的不同类型。 这就是Linq的工作原理:

Enumerable.Range(0, 1)    // RangeIterator
  .Where(i => i % 2 == 0) // WhereEnumerableIterator<int>
  .Select(i => i.ToString()) // WhereSelectEnumerableIterator<int, string>
  .Where(i => i.Length != 1) // WhereEnumerableIterator<string>
  .ToList();                 // List<string>

当每个操作作用于IEnumerable<int>类型时,每个结果都由不同的类型实现。

像你建议的那样,变异流畅的方法在C#中非常罕见。 它们在没有C#支持的属性的语言中更常见,因为它很方便:

someObject.setHeight(23).setWidth(143).setDepth(10);

但是在C#中,这样的setXXX方法很少见,属性设置器更常见,并且它们不能流畅。

主要的例外是StringBuilder因为它的本质意味着在不同的值上反复调用Append()和/或Insert()非常常见,而且流畅的风格很适合。

否则,变异流畅方法并不常见的事实意味着你提供的所有东西都是返回该领域的额外成本。 这是微不足道的,但是当与更惯用的C#风格一起使用时,它将无法获得任何东西。

要有一个外部方法,它既可以变异也可以返回变异对象,这可能会导致某人认为你没有改变对象,因为你返回了结果。

例如,看到:

public static IList<T> SortedList(IList<T> list);

使用代码的人可能会认为在呼叫list被单独存放之后,而不是在适当的位置进行排序,并且两者将是不同的并且可以单独进行变更。

仅仅因为这个原因,要么返回一个新对象,要么返回void以使变异性更明显。

我们可以在返回新对象时使用快捷方式:

public static T[] SortedArray<T>(T[] array)
{
  if (array.Length == 0) return array;
  T[] newArray = new T[array.Length];
  Array.Copy(array, newArray, array.Length);
  Array.Sort(newArray);
  return newArray;
}

在这里,我们利用了这样一个事实,即由于空数组本质上是不可变的(它们没有要变异的元素,并且它们不能被添加),因此返回相同的数组与返回新数组相同。 (通过返回this比较string如何实现ICloneable.Clone() )。 除了减少完成的工作量外,我们还减少了分配数量,从而减少了GC压力。 即使在这里,我们也需要小心(有人对关于对象身份的集合进行关键会受到阻碍),但在许多情况下它会很有用。

简短的回答 - 这取决于。

答案很长 - 如果您使用构建器模式或需要链接方法,我会考虑返回对象的实例。

大多数其他情况看起来像代码味道:如果您控制API并且发现很多地方没有使用您返回的对象,那么为什么还需要额外的努力呢? 可能你会创造微妙的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM