C# Vincular parámetros de constructor a variables de instancia

Very common scenario: I have a class with multiple instance variables and a constructor that accepts multiple parameters. Can I somehow bind one to the other? Assigning all parameters to the instance variables is very verbose and is one of the situations that could be (and should be) covered by the convention-over-configuration principle. My example code looks like this:

public class myClass
{    
    private object param1;
    private object param2;
    private object param3;
    private object param4;

    public myClass(object param1, object param2, object param3, object param4)
    {
        this.param1 = param1;
        this.param2 = param2;
        this.param3 = param3;
        this.param4 = param4;
    }
}

Hay un fácil way to get rid of this and let C# do its magic automatically?

preguntado el 28 de agosto de 12 a las 13:08

Plugins like CodeRush or JustCode can generate that code automatically for you. -

You could also look at using code snippets: msdn.microsoft.com/en-us/library/ms165392(v=vs.80).aspx However, tools such as those mentioned by BigYellowCactus will give you better productivity. -

Add Resharper to the list above. -

@Jan Can you spell out, very literally and precisely, the convention you're proposing? -

@Serg, "map constructor parameters to instance variables of same name and same type" -

3 Respuestas

There's nothing within the C# language which covers this, no. While tools can generate code for you, they may not necessarily keep it up to date and you'll still end up with the code present and visible. You could la posibilidad do this in some scenarios using reflection, e.g.:

public MyClass(object param1, object param2, object param3, object param4)
{
    Helpers.PopulateFromConstructor(this, param1, param2, param3, param4);
}

... where you'd need to specify the values in the same order as the parameters, and keep the names the same as the fields etc. You may also find there are problems when the fields are readonly.

Personally I'd just suck it up - use tools to generate the code if you want, but otherwise just live with it.

Note that you may want to do validation as you set the fields, particularly around nullity. So your constructor body may realmente end up like this:

public myClass(object param1, object param2, object param3, object param4)
{
    this.param1 = Preconditions.CheckNotNull(param1);
    this.param2 = param2;
    this.param3 = Preconditions.CheckNotNull(param3);
    this.param4 = param4;
}

(For a suitable Preconditions class, of course. I've gratuitously nicked the idea from Guava in Java code, as I use that in day-to-day coding. This is the approach we use in Hora de Noda también.)

Respondido 28 ago 12, 13:08

"... could be (and should be) covered by the convention-over-configuration principle..."

"Convention over configuration" typically applies to an API or framework, such as MVC or Entity Framework, not to the language itself. An API is typically a focussed, reusable, and above-all simplificando abstraction of functionality. In this situation, dictating convention can help to drive structure without compromising functionality.

However, this is not true of the programming language. The language is broad, and low-level, and complex by comparison. It should restrict its user as little as possible without diluting the value of the language. Assuming such a broad "convention" would be very prescriptive. Beyond this, it would be dangerous of the compiler to assume that a parameter with a given name debe siempre be assigned to a private field of similar name.

For one, your convention isn't the only commonly-used one. For exqample, one common coding styles suggests underscore-led private fields (_param1), which your convention would miss. The constructor might have further logic beyond just those assignments, in which case your convention is too simple: should the "convention-driven" code be executed before or after any other constructor logic?

Most importantly, how would such a convention be overridden? If, in the constructor, you were to consume param1 in some other way, do you still execute the convention? What if, in the constructor, I assign a different value to this.param1? Should your convention occur before or after the code that the user has added?

Even these brief questions - for which many people will have very different and equally valid answers - are enough to suggest that such a convention is not as obvious, nor easily defined, as it might seem.

Respondido 28 ago 12, 13:08

Wow, very many good points. I guess what I'm looking for is another chapter in the fight of "make my life easy" versus "keep my life flexible". I guess Andras answer is the best/easiest yet most flexible way to do it. - Ene

And one of the situations where I'd love to accept 2 answers! - Ene

While there are many plugins that can do this kind of thing - it's worth noting that if you VS2010+'s native ability to generate constructors from a model call when a matching constructor does not exist, you can use a simple keyboard shortcut to do the work for you.

I.e. if I a stub class:

class MyClass{

}

And then in a method somewhere I write something like this:

object p1, p2, p3;
//...  (get values for p1-3)
var a = new MyClass(p1, p2, p3);

When such a constructor does not exist, a little helper button appears. If you click on that, or press ALT+SHIFT+F10 (by default) you get a menu, one of the options on which is to generate a stub constructor, which will then change the MyClass codificar de la siguiente manera:

class MyClass
{
    private object p1;
    private object p2;
    private object p3;

    public MyClass(object p1, object p2, object p3)
    {
        // TODO: Complete member initialization
        this.p1 = p1;
        this.p2 = p2;
        this.p3 = p3;
    }

}

Respondido 28 ago 12, 13:08

+1: You can also use ctrl + . to reach the same menu (at least in VS2010 Express). - John H

Cool - that's significantly easier than the three-key version! - András Zoltán

Thats really cool. Thanks heaps. Not 100% what I was hoping for, but as Dan pointed out, I was too focused on my current situation and did not consider many relevant aspects. So I guess Ctrl+. it is :) - Ene

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.