views:

88

answers:

5

AFAIK, It's agreed that accessing virtual members from constructor is a dangerous practice. Can we overcome this through using an additional step, a method, to make required initialization? like the following:

public class EntityAlpha {
    public virtual string Value { get; protected set; }

    public EntityAlpha(string value) {
        Value = value;
    }
}

to be replaced with

public class EntityAlpha {
    public virtual string Value { get; protected set; }

    public EntityAlpha(string value) {
         AssignValue(value);
    }

    private void AssignValue(string value) {
        Value = value;
    }
}

What are consequences of using this additional method? Does it still dangerous like using virtual member in constructor or worst?! How to test if this assumption is not harmful?

+10  A: 

You effectively have the same problem, only now the code is more difficult to read.

The key is designing your class so that the constructor won't reach any virtual members, even indirectly through other methods.

Greg
"Now you have two problems"
Marc Bollinger
This question popped up during using NHibernate. So that means I shouldn't use Auto-Properties. I should use backing fields better. Right?
Waheed Sayed
@Waheed - Yes, I think that would be best. Use a private backing field and set the backing field from your constructor.
Greg
+4  A: 

That doesn't change anything, you're still calling a virtual method from the constructor, you've just put another layer in between.

ho1
+1  A: 

It is as dangerous as using it from the constructor. It will simply call the overriden implementation. And compiler will probably inline the AssignValue function, so the real code will look the same as previous.

Paja
+4  A: 

This is still just as dangerous; all you're doing is hiding the danger and obfuscating the code.

If Value is backed by an actual data field, say m_Value, you can prevent the problem by assigning to m_Value directly.

Thomas
You suggest an excellent solution.
Greg
+1  A: 

I think it would have the same effect in this case. If you were to inline the new method you get the exact same code so I'm guessing it will compile exactly the same. If you take a step back are you breaking the Liskov Substitution Principle? It seems that you might have created a hierarchy that isn't advisable.

Jerod Houghtelling