简体   繁体   中英

The correct way to modify an object that is being passed as a parameter into the modifying class

What is the best way of the following 2 suggestions to modify a property on an object that is being modified by a class that accepts the object as a parameter?

  1. Have the class work on the object and a return a value which you then assign to the object

or.

  1. Pass the object in using the ref keyword and have the class amend the object without actually returning anything.

For example, I have a Person object with a First Name and Last Name and 2 different ways to create the Full Name.

Which is the best way?

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

You don't need ref . Just modify the object in your method.

When an reference type is passed as a parameter, it is passed "by reference", not by value. So when you modify it, you're actually modifying the original object. You only need ref if you are passing a value type such as an int .

I say "by reference" in quotes, because what is actually happening is that an internal "pointer" to the original object is being passed by value .

First things first

The fact that you're mentioning ref suggests that you are missing a fundamental notion; that is, code that can access a reference to an object can by definition have access to the actual object.

The only conceivable usage scenario in which you would use a ref parameter is when you want to set that reference to some other object, or to null .

If you don't use ref (or even out for that matter, see the difference here ) you are actually passing your argument by value, which means that a copy of it is created.

This means two things, depending on whether the parameter is a value type (like int, long, float etc) or a reference type (reference to an instance of whatever class).

If a parameter is a value type, a copy of it will be created. Your method can then do whatever it wants to it, because the copy is only limited to that method's scope.

If a parameter is a reference type, however (as your Person would be), only the reference itself gets copied: the underlying object is the same. This is where the big difference lies. Keep in mind, however, that the reference you have available inside the method is still a copy of the original one, which means that you can set it to null , set it to another object and, in short, do whatever you like with it: once the method has returned, that reference will disappear, and the original one will be left untouched.

That being said

As others told you, there's really no need to use ref .

Moreover, as long as you're dealing with trivial cases such as concatenating first and last name, I would let the object itself do it (exactly like Slapout did).

There's always time to separate responsibilities later should such a need arise.

Consider also that having a separate class for such a trivial task might be also considered counterintuitive. Say this is the code at hand:

var p = new Person() { FirstName = "John", LastName = "Smith"} ;

Console.WriteLine(p.FullName);

When I do that, I fully expect FullName to return something meaningful (ie "John Smith") at all times.

With both your approaches, instead, what will happen if I forget (and I will ) to call CreateFullName ?

Should you really need to move a given concern into a separate class, hide it inside the property's get method.

That way, people won't need to know about the underpinnings of the classes you wrote, and it's still testable.

Neither - and you don't need 'ref' - just use:

public void CreateFullNameB(Person person) 
{ 
    person.FullName = person.FirstName + " " + person.LastName; 
} 

At first, the only reason to separate the method into a other class is if that method have dependencies like database or network access. Otherwise that simple method should be a property of Person class.

Also it is only reason to pass whole object to method is when object data is widely used inside that method. Otherwise it is better to pass FirstName and LastName as parameters and return result.

Classes don't need to be passed with ref modifier to modify their content. ref is only required if method want assign parameter with a reference to a new instance.

In example you described if choose from two options the return value is better because it makes less coupling and separates logic from data representation. But if few properties of an entity can be updated, then passing object is better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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