Implementing generic class and multiple interfaces - c#

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

Related

Is it possible to restrict a base class to a specific subclass?

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

Circular generic types in inheritance - why does it work?

Consider the following:
public class EntityBase<TEntity>
{
public virtual void DoSomethingWhereINeedToKnowAboutTheEntityType()
{
}
}
public class PersonEntity : EntityBase<PersonEntity>
{
public override void DoSomethingWhereINeedToKnowAboutTheEntityType()
{
}
}
I added this into code and ran it and it worked ok, but I'm surprised that I can inherit a class who's definition is based on the inheriting class.
When I tried it I was expecting either it not to compile, or to fail once actually called.
You can do something similar with an interface:
public interface IEntityBase<TEntity>
{}
public class PersonEntity : IEntityBase<PersonEntity>
{}
I've actually switched my code from the former to the later, using the interface, but I'm still curious why this works.
It works because there's no reason why it wouldn't work. EntityBase<PersonEntity> doesn't inherit from PersonEntity, it merely references the type. There's no technical problem with a base class knowing about its own derived class. This also works (even though this specific example is a bad idea):
public class A
{
public B AsB()
{
return this as B;
}
}
public class B : A
{
}
I'm surprised that I can inherit a class who's definition is based on the inheriting class.
Careful - what you're inheriting is a class whose definition involves an arbitrary Type, is all. All of these are legal:
class O : EntityBase<object>
class S : EntityBase<String>
class Q : EntityBase<Q>
All you've said in the definition of EntityBase is that TEntity should be a type - well, PersonEntity is a type, isn't it? So why shouldn't it be eligible to be a TEntity? No reason why not - so it works.
You might be concerned about the order of definitions, but remember that within the unit of compilation, everything gets defined 'at once' - there's no sense in which PersonEntity needs to be compiled 'before' anything else (including itself!) can refer to it. Indeed, you're even allowed
class A : EntityBase<B>
class B : EntityBase<A>
for which no conceivable 'order of compilation' could work, if such a thing were needed.
A very simple example is the generic interface IComparable<T>. Usually, you implement it like this:
class MyClass : IComparable<MyClass> {/*...*/}
This implementation of the generic template is just saying that MyClass objects can compare to other MyClass objects. As you can see, there is no problem with the mental model. I can very well understand the concept of a class whose objects can compare between them without knowing anything else about the class.
The main point here is that template parameters are just used by the generic class or interface, but they need not be related by inheritance at all. IComparable<MyClass> does not inherit from MyClass. So there is no circularity.

Trouble with Interfaces, Inheritance, and Polymorphism

I have come to a point in my program where my polymorphism is broken. I realize that this is in my code, and I understand why; I'm just not sure how best to resolve it.
I have three model classes which have the same interface, but very significantly different implementations. I created an interface, and then three independent classes, which also derive from a ModelBase class:
public interface IMyModel
{ ... }
public class MyModelA : ModelBase, IMyModels
{ ... }
public class MyModelB : ModelBase, IMyModels
{ ... }
public class MyModelC : ModelBase, IMyModels
{ ... }
So far fine and dandy.
I have a ViewModel base class, which takes a model as a constructor:
public abstract class MyViewModelBase
{
public MyViewModelBase(ModelBase Model)
this.model = Model;
}
Now where I am caught; I want to have a concrete ViewModel class that can accept any of the three Model classes above:
public class MyViewModel : MyViewModelBase
{
MyViewModel(IMyModel Model) : base (Model) // <- Invalid Polymorphism!
{
// More here
}
}
This doesn't work, because it is possible for an implementation of IMyModel to not be based on ModelBase. The argument cannot be safely passed to the base constructor.
I can see one solution being to create an abstract base class derived from ModelBase for these models with exception-throwing content, and using that as the type in my ViewModel. I had started with a base class, but found that almost every part had some difference! However, that seems like a lot of work. Also, it won't ensure that derived classes implement everything (like an interface does). Finally, it seems to devalue the interface concept (indeed, I wouldn't need one anymore).
I don't see any way of marking the interface as saying that derived classes must have a specific base class. It would be nice if I could do this, but it's not allowed:
public interface IMyModel : MyModelBase
{ ... }
Is there a better way to do this?
Clarification:
I probably oversimplified the names here. I have other Models and ViewModels using the base classes, but not implementing the interface.
public class MyOtherModel : ModelBase // But not IMyModel!
{ ... }
public class MyOtherViewModel : MyViewModelBase
{
MyOtherViewModel(MyOtherModel Model) : base(Model) // This works
{ ... }
}
You could make your base class implement the interface, then inherit your implementation classes from the base class, marking the base class and methods as abstract (MustInherit/MustOverride in VB parlance). This would give you your polymorphism and guarantee the interface.
you could use generic constraints:
public class MyViewModel<T> : MyViewModelBase where T : IMyModel , ModelBase
{
MyViewModel(T model) : base (model) // T inherits ModelBase and implements IMyModel , so it is legal
{
// More here
}
}
Often (not always) when you find yourself building an Abstract Base Class it means you are trying to share both an interface and some common logic. Perhaps you can split these two things?
Move the common interface into IMyModels, and extract the common functionality into a separate class. Then include an instance of that helper class in each model. Essentially use composition to share functionality instead of inheritance.
Make ModelBase implement IMyModel. If ModelBase does not implement all methods of the interface, implement them as abstract methods.
To my understanding
Models are stupid Data containers
Interfaces describe behaviour and Functionality, not data.
So why bother putting interfaces on the models at all?
#Yochai : Good point, using Generics - saves code, but you must first declare base classes (only one per class, there's no mixed inheritance in C#), then any amount of interfaces, thus your code should be:
public class MyViewModel<T> : MyViewModelBase where T : ModelBase, IMyModel

Do generic classes have a base class?

I would like to pass a generic interface to a function:
private I<T> CreateStubRepository<T, I >()
where I : aGenericBaseClass
So i was wondering if generic interfaces implement a base class or specific interface?
I know by using reflection you can test if it is a generic class but I dont see that helping me
Well. What's the point of forcing the usage of any interface? I really do not get it (or your question).
You should more likely do something like this:
public interface IMyRepository<T>
{
}
public class Repository<T> : IMyRepository<T>
{
}
private IMyRepository<TEntity> CreateStubRepository<TEntity>()
{
return new Repository<TEntity>();
}
var repos = CreateStubRepository<User>();
Update
thanks for your answer but thats not what I am asking. What I want to know is does a class that implements a generic interface have a base class or does it inherit from an interface? I dont want to force any interface its more a question of is the object passed generic
Classes do not inherit interfaces. They implement them. The different is subtle but important.
A class can only inherit another class. This means that if you do not specify that a class inherits from another it will still inherit from object. And that wont change no matter how many interfaces a class implement.
class MyClass : ICoolInterface // inherits object
class MyList : ArrayList, ISomeInterface // inherits ArrayList
class MyGenericList<T> : IList<T> // inherits object.
Generic or non-generic classes can implement or inherit from generic or non-generic interfaces and classes. The only limitation is that the full type of any interface/class implemented/inherited from must be discernible given the full type of the class doing the implementing or inheriting. For example, a Foo<Bar> might inherit from FooBase and implement IDisposable; a FnordDuffleBag might inherit from DuffleBag<Fnord> and implement IReachInto<Fnord>.
Thanks for all the comments I think i was going in the wrong direction, What I was hoping for was that when I applied to a class the framework would know that it inherited from a base class or interface of say aGenericItemBaseClass before it constructed the class at runtime.
Yes I know that I can create a generic class with type parameters and use that but thats not what I was asking (although you may have got that impression from my posting).
At runtime I know that when using reflection I can determine if a class is generic by calling : IsGenericType which returns true if a type is generic.
So what I wanted to know which may have been explained poorly is, when using template types is there anyway to determine if that type is a generic type? It appears the answer is No the IL interperates the class as generic not the compiler.

can one class inherit from an other class an have implemented an interface at same time?

somthing like
public partial class RegistrationForm :
IRegistrationForm, System.Web.UI.UserControl
but this example does not work.
Yes, but you do it like this:
public partial class RegistrationForm : System.Web.UI.UserControl, IRegistrationForm
C# doesn't support multiple inheritance, so you put the class you inherit from first, followed by a comma, followed by a comma-delimited list of the interfaces it implements.
Absolutely, a class can inherit from a single base class and implement any number of interfaces at the same time.
Your example does not work because the one base class must be listed first, before all the interfaces...

Categories