abstract properties : get; vs. set; vs. get; set;  
Author Message
bitbonk





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

I would like to define an abstract property where the deriver is forced to implement the get acessor for that property but is free to implement the set acessor. It seems that C# 2.0 has no way of declaring this. Either the deriver has to implement both acessors (get; set;), or the deriver is not allowed to implement the acessor that was not declared in the abstract base class. I am suprised that acessors abstractness can not be controlled separately since the ultimately end up as methods anyway. Why is that so




Visual C#15  
 
 
TaylorMichaelL





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

The virtual attribute applies to the property (it's the member) and not its accessors. Therefore you can't do that. However you generally won't do that anyway. Whenever you make something virtual you take a hit at runtime as only at runtime can the actual member to be called be identified. Since properties are generally suppose to be quick like fields a virtual property is generally not the way to go but it is commonly done anyway (even in the framework).

There are two possible scenarios that I typically handle: a property is virtual or a property setter is virtual. Rarely is a property getter virtual and a property setter not so I'll ignore that case. For the best bang for your buck you should strive for the latter situation. To do so create the property as non-virtual and then call a virtual method in the setter.

public string Name
{
get { return m_strName ""; }
set { SetName(value); }
}

protected virtual void SetName ( string name )
{
...
}

This avoids the overhead of a virtual call in the general case of retrieving property values but still allows you to override the setter situation. If the property must be set by derived classes use constructors to enforce the policy. An alternative approach (used more in v2) is to use a protected property

public string Name
{
get { return NameCore; }
set { NameCore = value; }
}

protected virtual string NameCore
{
get { ... }
set { ... }
}

This is really not much of an improvement over simply making the public property virtual. However I personally try to avoid exposing public members as virtual because it limits the extensibility of the class (more so for methods than properties).

In summary I strongly recommend that a property getter never be virtual. Use a protected virtual method (or property) to allow overriding of the setter value. If you must be able to override both the getter and setter then make the entire property virtual but prefer to call a protected virtual property instead.

Michael Taylor - 12/11/06


 
 
bitbonk





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

just to make things clear, I wanted to declare the get acessor as abstract. And the set acessor may be implemeneted by the derived class. The set accessor was not be meant to be virtual. it feels somewhat stupid to do the following:



public abstract class Base

{
  public abstract string Property
  {
    get;
    set;
  }
}
public class ReadOnly : Base

{
  public ReadOnly(string property)
  {
    this.property = property;
  }
  private string property;
  public override string Property
  {
    get { return this.property; }
    set

    {
      throw new NotSupportedException("Property can not be" +
      "assigned to - it is read-only");
    }
  }
}
public class ReadWrite : Base

{
  public ReadWrite(string property)
  {
    this.property = property;
  }
  private string property;
  public override string Property
  {
    get { return this.property; }
    set { this.property = value; }
  }
}

 



 
 
Paul Louth





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

It does throw the meaning of the property into disarray though if you're splitting the responsibility for setting/getting between the base and subclasses.  Surely if you can override it, then you should let the subclass have the responsibility for setting and getting  

Do you have a concrete reason for doing this, rather than the mockup you've just shown us  


 
 
bitbonk





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

Yes I do have a concrete reason. I have a application that displays a treeview. Its items consist of "Base" Items. The Property "Property" is used as the display name for each item. So there is a generic algorithm that can operate on the tree using the "Base" items. For example new "Base" items can be added the the view or items can be moved. While it must be assured that this algorithm can read the display name of each "Base" item it never writes the name. For some of the Types that derive from "Base" however it would be convenient if the the Type had a set acessor for "Property" for the following reasons:

  • Instances of these derived Types will be displayed in a Windows Forms Propertygrid where the user may edit the "Property" property
  • Instances of these derived Types take part in other algorthims where the algorithm needs to modify the "Property" property


 
 
Paul Louth





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

I can't help feeling you're trying to put specialised code which belongs in the subclasses into the base.  If the base functionality of Base is that the  Property is read-only, then it shouldn't change in the subclasses.  If some subclasses should be able to modify the property, then I think that should be done with a seperate method: SetProperty.  I appreciate that it doesn't really help too much where the Windows Forms designer is concerned, but you shouldn't break your app for a bit of convenience.

 


 
 
bitbonk





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

Well, I still don't see why it must not be possible to declare: "All items of this type must implement the get acessor for "Property" and they can do what they want with the set acessor." Why can I declare such using interfaces but cannot using abstract classes



 
 
Paul Louth





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

No the point is that if a property from the base-class indicates that set and get are supported then all subclasses should implement them.  If they can't implement them then that functionality shouldn't be in the base class, because it doesn't represent functionality which is common to all.

 


 
 
TaylorMichaelL





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

You can not declare a property getter as abstract and the setter as virtual in an interface. All members are abstract in an interface. I agree with Paul that the design you're trying for doesn't make a lot of sense. However you can accomplish it through this mechanism.

public abstract class Base
{
public virtual string Property
{
get { return PropertyCore; }
set { ... }
}

protected abstract string PropertyCore { get; }
}

However, as Paul said, this doesn't allow you to let some classes implement setters and some not. All classes would have a setter. In general you should avoid the NotSupportedException as it is a sign that your design is not broken up well. Instead create a base class that allows read only access while a derived class exposes read and write access. The property names would have to be different though. This gives you compile-time checking that you want rather than waiting until runtime (with the exception route).

Michael Taylor - 12/11/06


 
 
James Curran





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

Let's try a variation of Michael's design:


public abstract class ReadOnly
{
public abstract string PropertyR
{ get; }
}

public abstract class ReadWrite : ReadOnly
{
public abstract string Property
{ get;
set;
}
}
public class MyClass : ReadWrite
{
public override string Property
{
get { return this.PropertyR; }
set { myProperty = value;}
}

string myProperty;
public override string PropertyR
{ get {return myProperty; }
}
}

Class which derive from ReadOnly have a property called PropertyR which can only be read. Classes which derive from ReadWrite has a property called Property which can be read & written (as well as a PropertyR property). This gives two different way to read the property, which is bad but not serious (having two different way to write the property would be serious)



 
 
Paul Louth





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

I can't help feeling that's a little messy James.  Here's my preferred method:

public abstract class Base
{
    public abstract string GetProperty();
}

public class ReadOnly : Base
{
    protected string property;

    public ReadOnly(string property)
    {
        this.property = property;
    }

    public override string GetProperty()
    {
        return property; 
    }
}

public class ReadWrite : ReadOnly
{
    public ReadWrite (string property) : base(property)
    {
    }

    public void SetProperty(string property)
    {
        base.property = property;
    }
}

I completely do away with the idea of the Property property, and just go with old-style Get and Set.  The base functionality represents the common functionality for all items that derive from Base, namely that they must provide a GetProperty.  The ReadOnly class only implements what it needs to, and doesn't have any **** NotImplementedExceptions, and the ReadWrite class adds extra specialised functionality: the SetProperty method.

I know it's not quite as nice as a property, but it's consistent and effective.  It means all property access looks like foo->GetProperty and foo->SetProperty, rather than foo->PropertyR, foo->Property etc.

Alternatively:

public abstract class Base
{
    public abstract string Property
    {
        get
    }

}

public class ReadOnly : Base
{
    protected string property;

    public ReadOnly(string property)
    {
        this.property = property;
    }

    public override string Property
    {
        get
        {
            return this.property;
        }
    }

}

public class ReadWrite : ReadOnly
{
    public ReadWrite (string property) : base(property)
    {
    }

    public void SetProperty(string property)
    {
        base.property = property;
    }
}

This second method allows the base functionality to have a property, whilst providing specialised functionality in the ReadWrite subclass only.  This means the most common access is via foo->Property, but specialised modifications are via foo->SetProperty.  Less consistent but maybe more useful  

 
 
James Curran





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

True, but you missed a key point made by the OP:

Instances of these derived Types will be displayed in a Windows Forms Propertygrid where the user may edit the "Property" property

In other words, this has to be an actual property to work.



 
 
Paul Louth





PostPosted: Visual C# Language, abstract properties : get; vs. set; vs. get; set; Top

 

True, but you missed a key point made by the OP:

Instances of these derived Types will be displayed in a Windows Forms Propertygrid where the user may edit the "Property" property

In other words, this has to be an actual property to work.

I did read that, but for some reason I read it as Windows Form Designer, not PropertyGrid :o)

I still feel that it's not a good solution, and is breaking good design for the sake of the UI, which I always find quite disturbing.  Maybe a UI proxy object or a method of populating the PropertyGrid manually.