繁体   English   中英

将对象作为方法参数传递,然后让方法返回相同的对象

[英]Pass an object as a method parameter and then have the method return the same object

请参见下面的代码:

var MyViewModel = new MyViewModel();
var MyDomainModel = AutoMapper.Map<MyDomainModel>(MyViewModel);
MyDomainModel = service.DoSomething(MyDomainModel);

MyDomainModel引用被以下类型的返回类型覆盖:service.DoSomething();

在这种情况下,我应该通过引用传递MyDomainModel还是没有太大的不同?

我正在看很多上面编写的代码,如果有我不知道的原因,我在徘徊。

如果如注释所示, DoSomething仅修改传入的对象的属性,但返回相同的对象,则可以替换

MyDomainModel = service.DoSomething(MyDomainModel);

service.DoSomething(MyDomainModel);

没关系,因为无论哪种方式MyDomainModel仍将引用同一对象。

如果DoSomething方法将输入参数更改为指向新对象,则必须使用ref否则我看不到ref传递的意义。

编辑

如果正如您在注释中提到的那样,您仅更改输入参数的状态,则根本不需要将引用返回给传入的对象,因为更改在方法调用后将保持不变。

实际上,无论输入参数是否由ref传递,都没有理由返回传递的对象的相同引用。因此,可以将方法设置为service.DoSomething(MyDomainModel); 返回void

这里有两种可能的情况。

原始实例已修改

public MyDomainModel DoSomething(MyDomainModel model)
{
    model.Property1 = X;
    model.Property2 = Y;

    return model;
}

然后,您必须将原始实例作为参数传递,但是由于类是通过引用传递的,因此您可以将函数转换为void:

public void DoSomething(MyDomainModel model)
{
    model.Property1 = X;
    model.Property2 = Y;
}

var MyViewModel = new MyViewModel();
var MyDomainModel = AutoMapper.Map<MyDomainModel>(MyViewModel);
service.DoSomething(MyDomainModel);

// MyDomainModel.Property1 is set to X now...

原始实例已替换

public MyDomainModel DoSomething(MyDomainModel model)
{
    // ...

    return (new MyDomainModel());
}

在这种情况下,如果该方法不使用model ,则基本上可以避免将其作为参数传递:

public MyDomainModel DoSomething()
{
    // ...

    return (new MyDomainModel());
}

var MyViewModel = new MyViewModel();
var MyDomainModel = AutoMapper.Map<MyDomainModel>(MyViewModel);
MyDomainModel = service.DoSomething();

否则,如果该方法创建了新实例并保留了一些旧实例的属性,则必须保留该实例:

public MyDomainModel DoSomething(MyDomainModel model)
{
    MyDomainModel newModel = new MyDomainModel();
    newModel.Property1 = model.Property1;

    return newModel;
}

var MyViewModel = new MyViewModel();
var MyDomainModel = AutoMapper.Map<MyDomainModel>(MyViewModel);
MyDomainModel = service.DoSomething(MyDomainModel);

这取决于方法的作用。 对象总是以这种使用方式通过引用传递(尽管简单地说“通过引用传递”并不能真正解释幕后发生的事情),因此,如果DoSomething操纵MyDomainMidel,则该方法返回时,更改将继续存在。 但是,如果DoSomething创建了一个新的域模型实例并返回了该实例,而您想保留它,则必须保留返回的值

这里有些例子:

//the passed in person is renamed, you don't need to capture the return value
public Person Rename(Person p){
  p.Name = "John";
  return p;
}

//the passed in person is not renamed, you need to capture the return value
public Person Rename(Person p){
  p = new Person();
  p.Name = "John";
  return p;
}

//the passed in person is swapped out for a new one, you don't need to capture the return value
public Person Rename(ref Person p){
  p = new Person();
  p.Name = "John";
  return p;
}

最后一个示例与中间示例有所不同,这要归功于ref关键字。 您可以设想,在中间调用的情况下,您在调用方法中有一个人,然后调用Rename (myPerson) ,并且框架创建了对person对象的引用的副本,并将该副本引用传递给了被调用的方法。 。 如果被调用的方法操纵实例的属性,则即使通过复制引用访问原始实例,该原始实例也会被修改。 如果复制引用指向整个新对象,则对属性的任何更改都会影响新对象,而不是原始对象。 当方法返回时,复制引用超出范围,并且编辑操作丢失,因为复制指针静默消失,因此,如果需要,为什么需要捕获返回值

如果使用ref关键字,而不是传递对myPerson的引用的副本,则传递对实例的原始引用。 如果该方法将其指向一个新的对象实例,则当控件返回到调用方法时,它将发现其myPerson实例已被一个全新的对象替换。 这种方法的用例范围很窄,因此不是一种首选的编程方式,因为它本质上赋予了调用的方法超出其职责范围的能力。 调用方法可能不喜欢将其可变内容丢弃并替换为方法调用。 几乎总有一种避免使用ref ,虽然您不清楚ref的机制,但最好避免使用它,即使它确实意味着您必须像中间示例一样进行编码。

您经常像中间示例那样编写代码,也许没有意识到。 字符串是不可变的,因此每次调用.Substring都会创建一个表示较短字符序列的新字符串,因此您必须保留返回值。 结果,一些开发人员甚至习惯于只操作现有对象的属性而从不使用new关键字的方法

暂无
暂无

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

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