以下 2 个建议中修改正在由接受对象作为参数的类修改的对象的属性的最佳方法是什么?
或者。
例如,我有一个具有名字和姓氏的 Person 对象,以及创建全名的 2 种不同方法。
哪个是最好的方法?
public static void Main()
{
Person a = new Person { FirstName = "John", LastName = "Smith" };
Person b = new Person { FirstName = "John", LastName = "Smith" };
NameProcesser np = new NameProcesser();
// Example A
a.FullName = np.CreateFullNameA(a);
// Example B
np.CreateFullNameB(ref b);
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
}
public class NameProcesser
{
public string CreateFullNameA(Person person)
{
return person.FirstName + " " + person.LastName;
}
public void CreateFullNameB(ref Person person)
{
person.FullName = person.FirstName + " " + person.LastName;
}
}
你不需要
ref
。只需修改方法中的对象即可。
当引用类型作为参数传递时,它是“按引用”传递,而不是按值传递。所以当你修改它时,你实际上是在修改原始对象。如果您要传递值类型(例如
ref
),则仅需要 int
。
我在引号中说“通过引用”,因为实际发生的是指向原始对象的内部“指针”正在通过按值传递。
您提到
ref
的事实表明您错过了一个基本概念;也就是说,可以访问对象引用的代码根据定义可以访问实际对象。
使用
ref
参数的唯一可能的使用场景是当您想要将该引用设置为某个其他对象或null
时。
如果您不使用
ref
(甚至不使用out
,请参阅此处的区别),您实际上是按值传递参数,这意味着创建了它的副本。
这意味着两件事,具体取决于参数是值类型(如 int、long、float 等)还是引用类型(对任何类的实例的引用)。
如果参数是值类型,则会创建它的副本。然后你的方法就可以做任何它想做的事情,因为副本仅限于该方法的范围。
但是,如果参数是引用类型(就像您的Person
那样),则仅复制reference 本身:底层对象是相同的。这就是最大的区别所在。但请记住,该方法中可用的引用仍然是原始引用的副本,这意味着您可以将其设置为
null
,将其设置为另一个对象,总之,可以做任何您喜欢的事情有了它:一旦方法返回,该引用将消失,并且原始引用将保持不变。话虽这么说
ref
。此外,只要您处理诸如连接名字和姓氏之类的琐碎情况,我就会让对象本身来完成它(就像 Slapout 所做的那样)。
如果出现这种需要,以后总有时间来分离职责。
还要考虑一下,为这样一个琐碎的任务建立一个单独的类也可能被认为是违反直觉的。 说这是手头的代码:
var p = new Person() { FirstName = "John", LastName = "Smith"} ;
Console.WriteLine(p.FullName);
当我这样做时,我完全希望
FullName
始终返回一些有意义的内容(即“John Smith”)。采用您的两种方法,如果我忘记(并且
我会)打电话CreateFullName
会发生什么?如果您确实需要将给定的关注点移至单独的类中,请将其隐藏在属性的
get
方法中。这样,人们就不需要了解您编写的类的基础,并且它仍然是可测试的。
public void CreateFullNameB(Person person)
{
person.FullName = person.FirstName + " " + person.LastName;
}
Person
类的属性。将整个对象传递给方法的唯一原因是当对象数据在该方法中被广泛使用时。否则,最好将 FirstName 和 LastName 作为参数传递并返回结果。
类不需要使用
ref
修饰符传递来修改其内容。仅当方法想要分配带有对新实例的引用的参数时才需要 ref。在您描述的示例中,如果从两个选项中进行选择,则返回值会更好,因为它可以减少耦合并将逻辑与数据表示分开。但如果实体的属性很少可以更新,那么传递对象会更好。