3

I have a line of C#:

cats.Add(new Cat("happy") { Mean=false})

I with to modify the Cat and then apply the mean like this:

cats.Add(Fix(new Cat("happy")) { Mean=false})

but I can't. How what should the Fix() method do in order for the above to work?

Ian Vink
  • 66,960
  • 104
  • 341
  • 555

3 Answers3

4

It won't work like that. The new X() { } is an initializer, and you can't split it up by calling a Fix around the constructor then the property / field bindings on the result. Property / field bindings must be evaluated before calling the Fix function.

You'd have to do this:

public Cat Fix(Cat cat) { ... }

cats.Add(Fix(new Cat("happy") { Mean=false }));

Or an extension method like this:

public static class CatExtensions {
     public static Cat Fix(this Cat cat) { ... }
}

cats.Add(new Cat("happy") { Mean=false }.Fix());

Or if you are a little more adventurous, you can accept an dynamic type:

public Cat Fix(Cat cat, dynamic properties) { ... }

cats.Add(Fix(new Cat("happy"), new { Mean=false }));

// extension method:
public static class CatExtensions {
     public static Cat Fix(this Cat cat, dynamic properties) { ... }
}

cats.Add(new Cat("happy").Fix(new { Mean=false }));

Or a generic method:

public Cat Fix<T>(Cat cat, T properties) { ... }

cats.Add(Fix(new Cat("happy"), new { Mean=false }));

// extension method:
public static class CatExtensions {
     public static Cat Fix<T>(this Cat cat, T properties) { ... }
}

cats.Add(new Cat("happy").Fix(new { Mean=false }));
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • 1
    But if Fix modifies the `Mean` property, this won't necessarily have the desired effect. He'd like to ensure `Mean` is set to false after the object has been created and 'fixed'. – Kenogu Labz Jun 21 '13 at 21:24
1

The above is not possible. An object initializer can only be used alongside a constructor, not on an arbitrary instance. You'll need to create a temporary variable:

var nonMeanCat = Fix(new Cat("happy"));
nonMeanCat.Mean = false;
cats.Add(nonMeanCat);

Alternatively, to support a fluent design, add explicit accessor methods for the properties, e.g. IsMean() and Mean(bool).

Kenogu Labz
  • 1,094
  • 1
  • 9
  • 20
1

As far as i know you can't do that because the syntax used in the first statement is called Object Initializer Syntax which is supported directly by the C# and can't extended. A solution is to have the Fix method return the Cat instance on which it was called, something like this:

public class Cat {
    public Cat Fix() {
        // DO YOUR WORK HERE
        return this;
    }

    public Cat Mean(bool meanValue) {
        Mean = meanValue;
        return this;
    }
}

Then you can do something like this:

cats.Add(new Cat("Happy").Fix().Mean(meanValue));
Ibrahim Najjar
  • 19,178
  • 4
  • 69
  • 95
  • 2
    I'm not sure that's valid; the assignment of the `Mean` property to `false` would cause the `cats.Add` method to receive an argument of type boolean, as opposed to the expected value of type Cat. See: http://stackoverflow.com/questions/3807192/why-do-assignment-statements-return-a-value – Kenogu Labz Jun 21 '13 at 21:33
  • 1
    @KenoguLabz, thank you for pointing that out, i wanted to show how could the fluent interface idea be implemented and in the mix i used it the wrong way. any way mistake corrected. – Ibrahim Najjar Jun 21 '13 at 21:43