“ref” 参数过多¶
ID: cs/too-many-ref-parameters
Kind: problem
Security severity:
Severity: recommendation
Precision: very-high
Tags:
- testability
- readability
Query suites:
- csharp-security-and-quality.qls
虽然使用 ref
传递方法参数有时是一种明智的做法(典型的例子是编写“交换”方法时),但过度使用引用参数会使方法不必要地难以理解和调用。
方法最终依赖于在其他地方正确初始化其参数,并且可能存在诸如别名之类的问题(当两个参数引用同一个对象时)。它们可能难以调用,因为引用必须引用左值(而不是临时对象),因此必须创建额外的对象来保存调用的结果。它们的结果也可能难以转发给其他方法。
建议¶
虽然并非在所有情况下都适用,并且必须加以判断,但一种常见的解决方案是创建一个新类,该类包装您尝试在方法中设置的值,然后修改该方法以返回它的新实例。
示例¶
在本例中,填充 name
、address
和 tel
字段是通过采用 ref
参数的方法完成的。这不是很好的做法,并且会使方法混乱。
using System;
class Bad
{
private static void PopulateDetails(ref string name, ref string address, ref string tel)
{
name = "Foo";
address = "23 Bar Street";
tel = "01234 567890";
}
private static void PrintDetails(string name, string address, string tel)
{
Console.WriteLine("Name: " + name);
Console.WriteLine("Address: " + address);
Console.WriteLine("Tel.: " + tel);
}
static void Main(string[] args)
{
string name = null, address = null, tel = null;
PopulateDetails(ref name, ref address, ref tel);
PrintDetails(name, address, tel);
}
}
最好将值包装在它们自己的 Details
类中,然后返回 Details
的新实例。它更容易正确传递给其他函数,也更容易理解。
using System;
class Good
{
class Details
{
public string Name { get; private set; }
public string Address { get; private set; }
public string Tel { get; private set; }
public Details(string name, string address, string tel)
{
Name = name;
Address = address;
Tel = tel;
}
}
private static Details PopulateDetails()
{
return new Details("Foo", "23 Bar Street", "01234 567890");
}
private static void PrintDetails(Details details)
{
Console.WriteLine("Name: " + details.Name);
Console.WriteLine("Address: " + details.Address);
Console.WriteLine("Tel.: " + details.Tel);
}
static void Main(string[] args)
{
PrintDetails(PopulateDetails());
}
}