返回值,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

返回值,Ref, Out是否有区别

在本例中:

public MyObject Update(MyObject object)
{
    object.thisA = GetValue1();
    // update state of object
    return object;
}

没有改变MyObjects的引用,所以:

    不需要返回对象
  1. 不要需要使用ref
  2. 不要需要使用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#中,实参可以通过valuereference传递给形参。

如果您的MyObjectreference type(例如:class),那么它被传递给reference的功能,因此您将最终修改相同的对象。换句话说,您对该实例(在函数内)所做的任何更改都将对该实例产生直接影响,并且在当前执行环境中将继续生效。

另一方面,如果MyObjectvalue type(例如:struct),则将其副本传递给method。也就是说,即使您修改了方法中的成员,也不会改变值类型的原始实例。当涉及到值类型时,这是默认行为。

现在假设您想要修改值类型的原始实例。这只有在传递值类型的引用时才能实现。裁判出来了。使用这些关键字,可以通过引用传递参数。ref和out是有区别的,可以分开学习。但是,请记住上下文,ref和out都允许被调用的方法修改参数。ref意味着参数在进入函数之前有一个值。这样函数就可以读取或更改其中的值。另一方面,out意味着参数在进入函数之前没有正式值。被调用的函数必须在参数从函数输出之前初始化它