tags:

views:

109

answers:

4

In the inherited class I use the base constructor, but can't use class's members calling this base constructor.

In this example I have a PicturedLabel that knows it's own color and has a image. A TypedLabel : PictureLabel knows it's type but uses the base color.

The (base)image that uses TypedLabel should be colored with the (base)color, however, I can't obtain this color: Error: Keyword 'this' is not available in the current context

A workaround?

/// base class
public class PicturedLabel : Label
{
    PictureBox pb = new PictureBox();
    public Color LabelColor;

    public PicturedLabel()
    {
        // initialised here in a specific way
        LabelColor = Color.Red;
    }

    public PicturedLabel(Image img)
        : base()
    {
        pb.Image = img;
        this.Controls.Add(pb);
    }
}

public enum LabelType { A, B }

/// derived class    
public class TypedLabel : PicturedLabel
{
    public TypedLabel(LabelType type)
        : base(GetImageFromType(type, this.LabelColor))
    //Error: Keyword 'this' is not available in the current context            
    {
    }

    public static Image GetImageFromType(LabelType type, Color c)
    {
        Image result = new Bitmap(10, 10);
        Rectangle rec = new Rectangle(0, 0, 10, 10);
        Pen pen = new Pen(c);
        Graphics g = Graphics.FromImage(result);
        switch (type) {
            case LabelType.A: g.DrawRectangle(pen, rec); break;
            case LabelType.B: g.DrawEllipse(pen, rec); break;
        }
        return result;
    }
}
+3  A: 

This error does make a lot of sense.

If you were allowed to use this in that way there would be a timing problem. What value do you expect LabelColor to have (ie, when is it initialized)? The constructor for TypedLabel hasn't run yet.

Henk Holterman
as you can see in the base class, I initialize it in the parameterless constructor. Finally, Let's say by default I declare `public Color LabelColor = Color.Red;`
serhio
But you are still in the process of calling that base ctor, so you are using LabelColor before it is set.
Henk Holterman
And declaring it with an initializer could solve this problem but that would not make `this` safe to use.
Henk Holterman
I think this is an explanation to the compile error which is quite obvious, but isnt a solution to the problem. It is a valid problem and the author is asking for a workaround here.
Fadrian Sudaman
yes. I can't use it before it's set. So...
serhio
The solution is very simply to use the default ctor from the base and assign the picture inside the body.
Henk Holterman
A: 

The property LabelColor is not initalized at the moment so it would be null. In fact, "this" is not initalized at that moment because the base constructor gets called before initalizing "this" which is why calling "this" cannot be done.

Oskar Kjellin
I understand. But searching a solution.
serhio
Perhaps take the LabelColor as a parameter to the constructor?
Oskar Kjellin
maybe is a good approach, but not for my case. The base class defines itself its own color.
serhio
+2  A: 

You are trying to access to a member that isn't initialized yet. this.LabelColor calls to the base class member that isn't available : you haven't called the base class constructor yet when you write : base(...)

 public TypedLabel(LabelType type)
        : base()
    {
        pb.Image = GetImageFromType(type, this.LabelColor);
    }
Seb
yeah... yeah... however. the color is in the base class, but the procedure is in the derived.
serhio
you'll have to make the picture box protected or provide a protected property to access the image in it for the derived classes.
Seb
+1  A: 

I think as a workaround I will implement this as below:

public class PicturedLabel : Label
{
    protected Image
    {
        get {...}
        set {...}
    }
    ............
}

public class TypedLabel : PicturedLabel
{
    public TypedLabel(LabelType type)
       :base(...)
    {
       Type = type;
    }
    private LabelType Type
    {
      set 
      {
         Image = GetImageFromType(value, LabelColor);
      }
    }
}

EDITED: I make the Type property private for this context, but it can also be public. In fact you can make Type and LabelColour public and whenever user change any of these properties, you can recreate the image and set it to your base class so that you can always guarantee a representative image is used in the picture box

Fadrian Sudaman