Shall the attribute properties be virtual? - c#

At MSDN an example to write a custom attribute shows the following strange behavior
[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
public virtual string Name
{
get {return name;}
}
// Define Level property.
// This is a read-only attribute.
public virtual string Level
{
get {return level;}
}
// Define Reviewed property.
// This is a read/write attribute.
public virtual bool Reviewed
{
get {return reviewed;}
set {reviewed = value;}
}
}
Why all properties are virtual?

There's section on the particular MSDN article that the OP mentioned that is about attribute "inheritance", i.e. if you have a class with a method that is virtual and is annotated with an attribute, and you add a subclass and override that method, will the subclass method have the attribute applied to it? That's what [AttributeUsage(AttributeTargets.Method, Inherited = false)] is about in the Inherited Property section.
Specifically:
public class MyClass
{
[MyAttribute]
[YourAttribute]
public virtual void MyMethod()
{
//...
}
}
Where YourAttribute is configured with AttributeUsage(AttributeTargets.Method, Inherited = false)] and MyAttribute has the default configuration.
public class MyClass
{
[MyAttribute]
[YourAttribute]
public virtual void MyMethod()
{
//...
}
}
public class YourClass : MyClass
{
// MyMethod will have MyAttribute but not YourAttribute.
public override void MyMethod()
{
//...
}
}
The default value for Inherited is true.
So in short, those properties are virtual in the article to describe this feature.

I doubt that there is any specific reason to do so, because Attributes work well with or without virtual specifiers on their properties or other members.
public string Name
{
get {return name;}
}
// Define Level property.
// This is a read-only attribute.
public string Level
{
get {return level;}
}
// Define Reviewed property.
// This is a read/write attribute.
public bool Reviewed
{
get {return reviewed;}
set {reviewed = value;}
}
Will work just as fine.
But you won't be able to override these methods in derived attribute classes.
For example, this will work:
public class WithVirtualPropAttribute : Attribute
{
public virtual String Prop {get; set;}
}
public class DerivedFromWithVirtualPropAttribute : WithVirtualPropAttribute
{
// Compiles ok
public virtual String Prop {get{return "0"} set{}}
}
This won't:
public class WithoutVirtualPropAttribute : Attribute
{
public virtual String Prop {get; set;}
}
public class DerivedFromWithoutVirtualPropAttribute : WithoutVirtualPropAttribute
{
// Compilation error !!!!!!!!!!!!!!!!!!!!!!!!!!
public virtual String Prop {get{return "0";} set{}}
}
It can be a design decision for some specific scenarios, but as overall there is no need do so.

Related

Enforce getter setter access at the interface level

I want to enforce access on getter or setter for a property at the interface level so that the same be followed in the class that implements it. I want to do something like below:
public interface IExample
{
string Name
{
get;
internal set;
}
}
public class Example : IExample
{
private string _name = String.Empty;
string Name
{
get
{
return _name;
}
internal set
{
_name = value;
}
}
}
But unfortunately from what I know this is not allowed in C#. I think that is because interface are meant to only expose what that is with a public access(I haven't the slightest idea!).
What I need here is a way to implement this using any other coding pattern (preferably using interface) which will help me to enforce specific access on getter or setter of a property in all of its implemented classes.
I googled this and tried to go through MSDN docs for this but had no luck!
Using internal on a setter is somewhat nasty anyway but if you really want to do it you could define a second interface that is itself internal AND make Example internal to your assembly.
public interface IExample
{
string Name
{
get;
}
}
internal interface IExampleInternal
{
string Name
{
set; get;
}
}
internal class Example : IExample, IExampleInternal
{
public string Name { get; set; } = string.Empty;
}
Now anything in the same assembly can take an IExampleInternal and outside only ever gets to see IExample. You do however have to list both interfaces on every class you create.
How about this? This can be a workaround:
// Assembly: A
public interface IExample
{
string Name { get; }
}
// Assembly: B
using A;
public abstract class Example : IExample
{
public string Name { get; protected internal set; }
}
public class SpecificExample : Example
{
public void UpdateName(string name)
{
// Can be set because it has protected accessor
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
IExample e = new SpecificExample()
{
// Can be set because it has internal accessor
Name = "OutsideAssemblyA"
};
}
}
// Assembly: C
using A;
public abstract class Example : IExample
{
public string Name { get; protected internal set; }
}
public class AnotherSpecificExample : Example
{
public void UpdateName(string name)
{
// Can be set because it has protected accessor
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
IExample e = new AnotherSpecificExample()
{
// Can be set because it has internal accessor
Name = "OutsideAssemblyA"
};
}
}
This works but you have to create (or copy-paste) the abstract class Example in every assembly in which you would like to create a specific implementation of it, e.g. SpecificExample or AnotherSpecificExample.
this is not possible. As everybody told you, interfaces are meant to define public access. How about the following code ?
public interface IExample
{
string Name
{
get;
}
}

Interface with get property, abstract class with get, subclass with get and set

I'm trying to have an interface which declares that a property must have a get:
public interface IValue {
public int Value { get; }
}
And then have an abstract class also define it, but keep it abstract:
public abstract class BaseClass : IValue {
public abstract int Value { get; }
}
And then I want to allow a subclass to define the getter and add a setter:
public class SubClass : BaseClass {
public int Value { get; set; }
}
I get an error like:
'SubClass.Value' hides inherited member `BaseClass.Value'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword
If I try:
public class SubClass : BaseClass {
public override int Value { get; set; }
}
I get:
`SubClass.Value.set': cannot override because `BaseClass.Value' does not have an overridable set accessor
Is there any way to allow a subclass to optionally add a setter when inheriting from an abstract class that only defines a getter?
Update: Just to clarify, I know of the workarounds I can do. My goal was to see what's the cleanest way I can do this. The reason I don't just throw a public setter on BaseClass is because some subclasses of BaseClass may not have a public setter. The end goal is basically just provide a common Value getter for the times they're used commonly.
You can't override getter, and add new setter.
This is what your code is, when properties are compiled into get_Value and set_Value methods:
public interface IValue
{
int get_Value();
}
public abstract class BaseClass : IValue
{
public abstract int get_Value();
}
public class SubClass : BaseClass
{
public override int get_Value() { /* ... */ }
// there's no set_Value method to override in base class
public override void set_Value(int value) { /* ... */ }
}
There are at least three ways:
define new int Value property in SubClass (note, then there's a difference);
override Value property and add SetValue method in SubClass;
define setter in BaseClass and override property.
'SubClass.Value' hides inherited member 'BaseClass.Value'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword
Is a warning not an error. It just says that you have public int Value in both abstract and concrete classes. Your abstract class has implementation of this property so when you declare it again in concrete class you just replace it with new property. So compiler advice you to use 'new' word for that purpose.
To use public override int Value { get; set; } you have to mark it 'virtual' in base class. Only virtual members can be overriden.
Class A { public virtual int Value { get; set; } }
Class B : A { public override int Value { get; set; } }
P.S. Interface members are public and abstract by default. So if you declare getter and setter in interface - you have to implement it in a concrete class.
Try to use this code:
public interface IValue
{
int Value { get; set; }
}
public abstract class BaseClass
{
int value;
int Value { get { return value; } }
}
public class SubClass : BaseClass, IValue
{
public int Value { get { return Value; } set { this.Value = value; } }
}
It appears there simply isn't a way to add the set with an abstract class in the middle without declaring a setter up-front. I've tried a ton of different combinations, and no luck.
Finally, I ended up doing this, which isn't ideal, but at least lets me not have a setter everywhere.
public interface IValue {
public int Value { get; }
}
public abstract class BaseClass : IValue {
public abstract int Value { get; }
}
public class SubClass : BaseClass {
protected int val;
public int Value { get { return val; } }
public int SetValue (int value) { val = value; }
}
public class SubClassWithoutSetter : BaseClass {
public int Value { get { return 50; } }
}
Basically, just do a "classic" setter, since there doesn't seem to be a syntax that supports letting me add a setter property after the fact.
It'd be nice if C# would implement something like:
public int Value { override get; set; } // note: this does not work

Extends simple getter, setter Methods for Classes in C#

I have a abstract class 'Building':
public abstract class Building {
abstract public int ID {get;}
abstract public string name {get;}
}
the class (for example) Headquarter : Building has the Variables for these getter and setter methods. The Problem is I have to write in every Subclass
private int _ID = 1;
public int ID {
get {return _ID;}
}
Is there a way to create for example one getter setter method like ahead, in the abstract class and save the code, so that I only have to set the variables?
Thanks for helping.
Instead of making the properties abstract, you could make the setter protected, and/or allow them to be set in the constructor:
public abstract class Building
{
// Optional constructor
protected Building(int id, string name)
{
this.ID = id;
this.Name = name;
}
public int ID { get; protected set; }
public string Name { get; protected set; }
}
This moves the implementation into the base class, but still only allows the subclasses to set those values.
You can try adding a protected setter in base class and set the value in ctor of derived classes:
public class Building
{
public int Id{get;protected set;}
and in derived class:
public class Headquarter: Building
{
public Headquarter()
{
Id = 1;
}
}

Struggling to implement abstract property in derived class

This all got a little trickier than I had intended. I'm using the HistoricalReportWrapper class because I retrieve my data through an API which has made it not realistic to have HistoricalReport implement IReport directly.
public abstract class CormantChart : Chart
{
public abstract IReport Report { get; protected set; }
}
public abstract class HistoricalChart : CormantChart
{
public override HistoricalReportWrapper Report { get; protected set; }
public HistoricalChart(HistoricalChartData chartData) : base(chartData)
{
Report = GetHistoricalReport(chartData.ReportID);
}
protected HistoricalReportWrapper GetHistoricalReport(int reportID)
{
return SessionRepository.Instance.HistoricalReports.Find(historicalReport => int.Equals(historicalReport.ID, reportID));
}
}
public class HistoricalReportWrapper : IReport
{
public HistoricalReport inner;
public int ID
{
get { return inner.ID; }
set { inner.ID = value; }
}
public string Name
{
get { return inner.Name; }
set { inner.Name = value; }
}
public HistoricalReportWrapper(HistoricalReport obj)
{
inner = obj;
}
}
public interface IReport
{
string Name { get; set; }
int ID { get; set; }
}
The idea here is that when I am working inside of the HistoricalChart class I need to be able to access specific properties of the HistoricalReport. The rest of my program, however, only needs to have access to the HistoricalReport's ID and Name. As such, I would like to expose IReport's properties to the world, but then keep the details contained to the class.
As it stands, all the classes which inherit HistoricalChart generate a "does not implement inherited abstract member" as well as a warning on HistoricalChart indicating that I am hiding CormantChart's Report.
What's the proper way to declare this to achieve what I'd like?
Thanks
EDIT: Whoops, I missed an override. Now, when I try to override CormantChart Report I receive:
'CableSolve.Web.Dashboard.Charting.Historical_Charts.HistoricalChart.Report': type must be 'CableSolve.Web.Dashboard.IReport' to match overridden member 'CableSolve.Web.Dashboard.Charting.CormantChart.Report' C
EDIT2: Taking a look at C#: Overriding return types might be what I need.
Because
public HistoricalReportWrapper Report { get; protected set; }
is not an implementation of
public abstract IReport Report { get; protected set; }

c# inheritance help

I am fairly new to inheritance and wanted to ask something. I have a base class that has lots of functionality that is shared by a number of derived classes.
The only difference for each derived class is a single method called Name. The functionality is the same for each derived class, but there is a need for the Name distinction.
I have a property in the base class called Name. How do I arrange it so that the derived classes can each override the base class property?
Thanks.
Declare your method as virtual
public class A
{
public virtual string Name(string name)
{
return name;
}
}
public class B : A
{
public override string Name(string name)
{
return base.Name(name); // calling A's method
}
}
public class C : A
{
public override string Name(string name)
{
return "1+1";
}
}
Use a virtual property:
class Base
{
public virtual string Foo
{
get;
set;
}
}
class Derived : Base
{
public override string Foo
{
get {
// Return something else...
}
set {
// Do something else...
}
}
}
You can declare it with a virtual or abstract keyword in the base class, then the derived class can over-ride it
you need to declare your property (in the base clase) as virtual
To enable each derived class to override the property you just need to mark the property as virtual
class Base {
public virtual Property1 {
get { ... }
set { ... }
}
}
Well I'm not sure from your description that inheritance is actually the right solution to the problem but here's how you make it possible for a property to be overridden:
class Base
{
public virtual string Name { get; set; }
}
But do you need it to be writable? A readonly property may make more sense in which case this might work:
class Base
{
public virtual string Name
{
get { return "BaseName"; }
}
}
class Derived : Base
{
public override string Name
{
get { return "Derived"; }
}
}
In the base class:
public virtual string Name { get; set; }
In the derived classes:
public override string Name { get; set; }
However, if the only difference between the classes is that they have different names, I'd argue that instead of inheritance you should just use the base class with the Name set in the constructor:
e.g.
public class MyObject
{
public string Name { get; private set; }
public enum ObjectType { TypeA, TypeB, ... }
public MyObject(ObjectType obType)
{
switch (obType)
{
case ObjectType.TypeA:
Name = "Type A";
// and so on
}
}
}

Categories