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

时间:2017-12-28 23:04:22

标签: c# .net

请参阅以下代码:

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

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

在这种情况下,我是否应该通过引用传递MyDomainModel,或者它是否真的没有太大区别?

我正在查看很多像上面那样编写的代码,如果有一个我不知道的原因,我就会徘徊。

4 个答案:

答案 0 :(得分:3)

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

MyDomainModel = service.DoSomething(MyDomainModel);

service.DoSomething(MyDomainModel);

这没关系,因为MyDomainModel的任何一种方式仍然会引用同一个对象。

答案 1 :(得分:0)

如果DoSomething方法正在将输入参数更改为指向新对象,那么您必须使用ref否则我不会看到传递点按ref

修改

如果你在评论中提到你只是改变输入参数的状态那么根本不需要返回对传入的对象的引用,因为更改将方法调用后保持不变。

实际上,无论输入参数是否被ref传递,都不应该成为返回传入对象的相同引用的原因。因此,您可以制作方法service.DoSomething(MyDomainModel);返回void

答案 2 :(得分:0)

我们在这里有两种可能的情况。

原始实例已修改

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);

答案 3 :(得分:0)

这取决于方法的作用。对象总是以这种使用方式通过引用传递(尽管简单地说“通过引用传递”并不足以解释引擎盖下发生的事情),因此如果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对象的引用的副本,并将复制引用传递给被调用者方法。如果被调用的方法操纵实例的属性,则原始实例会被修改,即使它是通过复制引用访问的。如果复制引用指向一个完整的新对象,则对属性的任何更改都会影响新对象,而不是原始对象。当方法返回时,复制引用超出范围,并且当e拷贝指针静默消失时编辑丢失,因此如果需要,需要捕获返回值的原因

对于ref关键字,而不是传递myPerson的引用的副本,将传递对实例的原始引用。如果该方法将其指向一个新的对象实例,那么当控制返回到调用方法时,它将发现其myPerson实例已被一个全新的对象替换。用于此的用例很窄,并且它不是一种受欢迎的编程方式,因为它实际上使被调用的方法能够操纵超出其职责范围的事物;调用方法可能不会理解其变量内容被删除并被方法调用替换。几乎总有一种方法可以避免使用ref,虽然你不清楚它的机制,但最好避免使用它,即使它确实意味着你必须像中间例子一样编码。

你的代码很像中间的例子,也许没有意识到;字符串是不可变的,因此每次调用例如.Substring都会创建一个表示较短字符序列的新字符串,因此您必须保留返回值。因此,即使对于仅操纵现有对象的属性且从不使用new关键字

的方法,一些开发人员也会养成习惯。