返回值,Ref, Out是否有区别
本文关键字:有区别 是否 Ref 返回值 Out | 更新日期: 2023-09-27 18:04:19
我在做这个,
public Order Add(Order order)
{
order.thisA = GetValue1();
// update the state of object
return order;
}
如果我在这里使用Ref或Out会有什么好处吗?
进一步的实现需要我添加这个方法,
public Order[] UpdateCollection(Order[] orderCollection)
{
foreach(Order o in orderCollection)
o = Update(o);
return orderCollection;
}
请根据最佳实践告诉我。
背景:
目前我只返回订单的INT id但将来可能需要返回更多属性,这里是完整的上下文,
https://codereview.stackexchange.com/questions/97778/crud-operation-class
在本例中:
public MyObject Update(MyObject object)
{
object.thisA = GetValue1();
// update state of object
return object;
}
你没有改变MyObjects的引用,所以:
- 不需要返回对象
- 不要需要使用
ref
。 你 - 不要需要使用
out
。
你
使用out
用于初始化对象(必须在函数中赋值)。
MyObject obj; // didn't assign anything
Method(out obj);
public void Method(out MyObject obj){
obj = new MyObject(); // assigned
}
使用ref
是为了防止您可能改变方法内部对象的引用:
MyObject obj = new MyObject();
Update(ref obj);
public void Update(ref MyObject obj)
{
obj = new MyObject(); // changing the ref!!!
obj.thisA = GetValue1();
}
顺便说一句,在你的情况下,你不需要做任何事情:
public void UpdateCollection(Order[] orderCollection)
{
foreach(Order o in orderCollection)
Update(o);
}
public void Update(MyObject object)
{
object.thisA = GetValue1();
}
如果您有可能想要更改引用而不是对象的数据,则使用ref
的例子:
public void RetargetReference(ref List<string> originalList)
{
originalList = new List<string>();
originalList.Add("World");
}
List<string> inList = new List<string>();
inList.Add("Hello");
RetargetReference(ref inList);
这将改变inList
的引用。它现在将指向一个新的列表,其中包含一个条目"World"。包含"Hello"的列表将不再对您可用,除非您有另一个对它的引用。 ref
parameters在方法执行过程中,如果你想改变传入的参数,可以使用
out
将用于让方法创建一个新的对象实例,而不需要您可以传递一个值!
的例子:
public void CreateReference(out List<string> newList)
{
newList = new List<string>();
newList.Add("Hello World");
}
List<string> list;
CreateReference(out list);
之后,list
将指向新的List<string>
实例。在方法内部,您无法访问newList
实际"指向"的任何内容。你总是需要创建一个新的实例。
out
参数可能很有用。例如,下面的方法将返回一个表示成功的bool
和两个包含数据的out
参数:
public bool TrySplitString(string source, out string part1, out string part2)
{
part1 = String.Empty;
part2 = String.Empty;
string[] parts = source.Split('=');
if (parts.Length != 2)
return false;
part1 = parts[0];
part2 = parts[1];
return true;
}
对象通常在c#中通过引用传递,因此下面的方法实际上改变了方法"外部"的数据:
public void ChangeList(List<string> list)
{
list.Add("World");
}
List<string> inList = new List<string>();
inList.Add("Hello");
ChangeList(inList);
之后,inList
包含两个条目:"Hello"answers"World"。
有时你返回作为参数传入的对象的原因是,这允许所谓的"方法链接",你可以"写句子"而不是"命令"。您将在下一个示例中看到:
public static List<string> CreateList()
{
return new List<string>();
}
public static List<string> AddItem(this List<string> list, string item)
{
list.Add(item);
return list;
}
public static List<string> DoSomethingWithList(this List<string> list)
{
...;
return list;
}
你可以使用这段代码,然后像这样写:
List<string> list = CreateList().AddItem("Hello").DoSomethingWithList();
返回object
可以用来创建"方法链",像这样:
someObject.Update(MyObject object).MyObjectMethod1().MyObjectMethod2();
我不能真正锻炼你真正想要达到的目标。但是,我会给你一些基本的。
在c#中,实参可以通过value
或reference
传递给形参。
如果您的MyObject
是reference type
(例如:class
),那么它被传递给reference
的功能,因此您将最终修改相同的对象。换句话说,您对该实例(在函数内)所做的任何更改都将对该实例产生直接影响,并且在当前执行环境中将继续生效。
另一方面,如果MyObject
是value type
(例如:struct
),则将其副本传递给method。也就是说,即使您修改了方法中的成员,也不会改变值类型的原始实例。当涉及到值类型时,这是默认行为。
现在假设您想要修改值类型的原始实例。这只有在传递值类型的引用时才能实现。裁判出来了。使用这些关键字,可以通过引用传递参数。ref和out是有区别的,可以分开学习。但是,请记住上下文,ref和out都允许被调用的方法修改参数。ref
意味着参数在进入函数之前有一个值。这样函数就可以读取或更改其中的值。另一方面,out
意味着参数在进入函数之前没有正式值。被调用的函数必须在参数从函数输出之前初始化它