tags:

views:

108

answers:

5
using System;

namespace ConsoleApplication1
{ 
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(new B("MyName").Name);
        }
    }

    abstract class A
    {
        public A(string name)
        {
            this.GetType().GetField("Name").SetValue(this, name);
        }
    }

    class B : A
    {
        public B(string name)
            : base(name)
        {
        }

        public string Name
        {
            set;
            get;
        }
    }
}

Is it possible to do something like that?

+4  A: 

I can't stress how very, very, very bad this is. You are creating an inverse coupling that is convoluted, confusing and contrived, severely lacking in clarity, failing best practices and object oriented principals, which is going to create a maintenance and management nightmare for people implementing derivatives of your abstract class. Do the right thing!!

abstract class A
{
    protected A(string name)
    {
        Name = name;
    }

    public abstract string Name
    {
        get;
        protected set;
    }
}

class B: A
{
    public B(string name) : base(name)
    {
    }

    private string m_name;

    public override string Name
    {
        get { return "B Name: " + m_name; }
        protected set
        {
           m_name = value;
        }
    }
}
jrista
+1. You're saying exactly what I thought when reading the question. But I still think it is not as easy as that. CA will complain because you're executing code in the derived class before the base class is initialized (you are still in the constructor of A when calling the abstract setter). Of course, you could suppress it as long as you just assign the value to the field.
Stefan Steinegger
@Stefan: True, it is possible to have unexpected behavior if you are not careful. I think the real problem happens when implementing the same scenario in VB.NET, which has an odd order of precedence. In C#, the order in which initializers, constructors, and overridden methods are called is at least logical, and can be useful if used properly. In VB.NET, its a bit odd and unpredictable, hence the problem. But, it only occurs if you WRITE the code in VB.NET. If you compile the code in C#, and use it in VB.NET, it maintains the order that C# performs.
jrista
You sill face the problem in c#. When you implement a inherited class C which overrides the abstract Name, then you access one of the base class's properties or fields in the setter of the name. This field is not yet initialized, you're still in the base class's constructor when it is called. This could be a really bad thing, therefore the code analysis complains about this.
Stefan Steinegger
+1  A: 

It is possible, but i wouldn´t recommend to do that. The problem is that your base class knows to much about the class that are derived from it.

When you derive a class from your abstract base class that does not define the property Name you get an Exception on runtime.

If you expect that each class, that is derived from your base class, has a property Name, then it would be easier to define the Property Name in your abstract base class and set the property with you constructor.

Jehof
+1  A: 

It's really bad form to do that. Generally you should just call a method like 'SetPossibleData()', and force all children to implement it in a fashion they decide.

Why do you need to do this?

Noon Silk
A: 

Use GetProperty() Method,

public A(string name) 
    {
        this.GetType().GetProperty("Name").SetValue(this,name,null);
    }
adatapost
A: 

It would be really straight forward if every class initializes the fields and properties it defines. Why does B expect the base class initialize its Name?

abstract class A
{
    public A()
    {
    }
}

class B : A
{
    // I know, its trivial, but it does the same ...
    public B(string name) : base()
    {
        Name = name;
    }

    public string Name { set; get; }
}

The only thing I could think of why you wrote this code is that the base class has some logic to initialize the field. Straight forward would be to let the derived class call the logic, but initialize the field itself:

abstract class A
{
    public A()
    {
    }

    protected string GenerateName(string someArg)
    {
        // complicated logic to generate the name
    }

}

class B : A
{
    public B(string someArg) : base()
    {
        Name = base.GenerateName(someArg);
    }

    public string Name { set; get; }
}
Stefan Steinegger