I have the following situation:
I have a base read-only class with simple information
I have a second class that inherits from the base class, this class' members can be updated
public class ExtendedClass : BaseClass
{}
To check if a class can be updated I have an abstract class UpdatableRecord
This abstract class has a property RecordState ("Deleted", "Edited", "New", "None")
this property has the default value "deleted".
What is the best way to build the classes (use different interfaces?, how is the hierarchy?)
Related
Is it like a class can inherit from both an Interface and a base class?
Probably you mean multilevel inheritance, but it's just a chain of classes inheriting, starting from some base class.
It's like this example class structure:
public class Vehicle { ... } // base class
public class CombustionVehicle : Vehicle { ... } // intermediary class
public class Truck : CombustionVehicle { ... } // derived class
The Truck instance is still a Vehicle, so it still can use it's properties and methods (of course if the access modifier allows it).
I think you are confused here by the term multi layer.
multiple inheritance is not supported in C#. A class cannot directly inherit from more than one base class.
C# supports multilevel inheritance, which means that a class can inherit from a class that itself inherits from another class. For example:
I have a need where I would like to have a base class only available to one specific subclass. This is due to a limitation where you cannot define an Attribute as an inner class of a generic.
The reason we want to define the attribute within the generic is when you do that and set its type to protected, that attribute is now only available to subclasses of your base class, keeping your API clean.
As an example, consider the abstract class ExampleMarkupExtension<T> that inherits from MarkupExtension. I want to define the attribute StaticInfoAttribute as an inner class, so it is only available to subclasses of ExampleMarkupExtension<T>.
However, as mentioned, you can't define an attribute as an inner class of a generic, so my workaround is to create a second, non-generic ExampleMarkupExtensionBase class which inherits from MarkupExtension, define StaticInfoAttribute as an inner class there, then have the generic inherit from that class instead.
The issue is now I have an extra class in my hierarchy that anyone can subclass. While it's technically harmless, I like keeping my API surface area clean.
Example
ExampleMarkupExtensionBase : Non-generic abstract base class
This is the class that defines the attribute which should only be available to subclasses of this class. This class only exists because I can't put StaticInfoAttribute within the generic abstract base class ExampleMarkupExtension<T> below.
public abstract class ExampleMarkupExtensionBase : MarkupExtension {
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
protected class StaticInfoAttribute : Attribute {
public StaticInfoAttribute(string value) => Value = value;
public readonly string Value;
}
}
ExampleMarkupExtension<T> : Generic abstract base class
This is the class that holds the static members which are unique to the subclasses of this class. It does this by using the subclass as the type parameter for the base class (see the where clause). The value of the static field is set from the attribute, hence it only being of any use for this specific subclass of ExampleMarkupExtension above.
public abstract class ExampleMarkupExtension<T> : ExampleMarkupExtensionBase
where T : ExampleMarkupExtension<T> {
static ExampleMarkupExtension() => Value = typeof(T).GetRequiredCustomAttribute<StaticInfoAttribute>().Value;
public static readonly string Value;
public sealed override object ProvideValue(IServiceProvider serviceProvider)
=> Value;
}
Rationale
Some may ask what's the harm of leaving it as-is. Technically, there's nothing wrong with letting a person subclass ExampleMarkupExtensionBase. There's just no point to it.
For that matter, there's technically no harm with moving the StaticInfoAttribute outside of the class as well, removing the need for the non-generic base class entirely. I just chose the former approach as it's more important to restrict the attribute's usage than it is to stop someone from subclassing the base class.
As per our comments, you can use the EditorBrowsable attribute to hide the method from projects that reference it. Note however it just hides it from IntelliSense and if a user was to type out ExampleMarkupExtensionBase that the class still exists and is valid to be used.
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class ExampleMarkupExtensionBase : MarkupExtension
Let's say I have a class structure like this, where class Foo is a generic over a class hierarchy of Base, Derived1, etc.
abstract class Base {...}
class Derived1 : Base {...}
.
.
.
class Derivedn : Base {...}
class Foo<T> where T : Base
{
/// XXX is a placeholder - see below
void DoBar(XXX arg) {...}
...
}
Wanting DoBar() to operate on something derived from Base, does it make any difference if XXX is Base or is T ?
The constraint means that T has to be Base or one of its children; but within the scope of DoBar() it is going to treat it as an object of type Base either way -- so this seems superficially like it will make no difference. But I might be overlooking something more subtle.
If you set xxx to Base than your method parameter can be Base or any class derived from Base.
If you set xxx to T than your method parameter can be T class or any class derived from T.
So if you instantiate Foo class with the generic type of Derived1 for example, in the first case you can use Base or classes derived from Base and in the second case you can use only Derived1 or classes derived from Derived1
I have the following class definition:
public class SessionTreeManager<T>
: DataManager<T> where T : DataItem, IDeletable, IAnotherInterface
I only want T to be a DataItem and to implement the other two interfaces. The compiler seems to think I want T to be any of the 3 and gives build errors as my T in the class above doesn't implement all 3 and this class cant find methods to override.
Is this possible?
If I understand your question correctly, you have to do the following:
public class SessionTreeManager<T>
: DataManager<T>, IDeletable, IAnotherInterface
where T : DataItem {}
Which says, SessionTreeManager extends/implements DataManager, IDeletable and IAnotherInterface and the generic is constrained to DataItem.
You can also set the extends to DataManager<DataItem> as mentioned in the other comment, but then the parent methods will not be constrained to class T and will rather be constrained to its parent DataItem. This way all the methods of SessionTreeManager as well as its parent class DataManager will be constrained to the subclass of DataItem which is class T
Try this
public class SessionTreeManager<T> : DataManager<DataItem>, IDeletable, IAnotherInterface
I wrote a UserControl which is derived from a standard Control.
This UserControl has a Property which is a list of a abstract class.
But i get an Error of the PropertyGrid which say that it could not create a new instance of the abstract class because it's abstract.
What can i do to handle this?
Abstract classes cannot be created, they must be implemented.
An abstract class is a class that cannot be instantiated, but must be inherited from
This is why you see an error from the PropertyGrid.
You will need to create a base class that implements all or some of your abstract class or
you might be able to use an interface.
Abstact VS Interface.