C# interface inheritance: What does this code actually mean? - c#

I was playing around with the following quick tutorial to add a repo layer to my MVC4 app. Well I got everything going good eventually. Now I am trying to add a "domain / business" layer.
I am getting errors when I try but they are not the problem I want to ask. Esentially. What I need to know is what does the following code actually mean:
public class HeadRepo<TEntity> : IHeadRepository<TEntity> where TEntity : class
Specifically I am talking about the fact that I have declared an interface (I know what interfaces are and how they work) so here is the interface declaration:
public interface IHeadRepository<TEntity>
I am assuming that -TEntity- is a generic type and could even be called -XYZAnything- but the standard convention is -TWhatever-. The T prefix being important, perhaps I am wrong, if so please correct me.
When I implement this interface using the first line above. What is actually happening? Specifically what does the
where TEntity : class
actually do for me. This is the important part of the question as this is the part I don't understand and would like to know what phrases to google to learn more about it (some links would be cool).
Finally, I am trying to inherit from another class. I know the rules of inheritance fairly well. I can only inherit from a single class, but multiple interfaces etc. So when I add the following code:
public partial class Student : Model.Student, IHeadRepository<TEntity> where TEntity : class
and also this variant
public partial class Student : IHeadRepository<TEntity> where TEntity : class
Things should work, I am inheriting from the Model class auto generated by EF so I can extend it by adding properties and methods. Occasionally I am told that a property in the base class does not exist (I know exists in the base class and is public as it is EF auto generated, and I checked). So don't know why it does this, but more specifically I get this error on both attempts:
Constraints are not allowed on non-generic declarations
I am assuming this has something to do with the where TEntity : class bit (mostly because this is highlighted with a red underline). hence the question.
Any help would be much appreciated.

I am assuming that TEntity is a generic type and could even be called XYZAnything but the standard convention is TWhatever. The T prefix being important
That’s correct. IHeadRepository<TEntity> is a generic interface with the generic type parameter TEntity which is just a name you can choose freely to reference the concrete type. The prefix T is just a convention which you should also follow.
where TEntity : class is a constraint on the generic type parameter TEntity and essentially means that TEntity should be a reference type. The general syntax is TEntity : SomeType which means that TEntity needs to be a subtype of SomeType. There are three special cases:
where TEntity : class – TEntity needs to be a reference type (i.e. created with class Something)
where TEntity : struct – TEntity needs to be a value type (i.e. created with struct Something)
where TEntity : new() – TEntity needs to have a default constructor, so you can use new TEntity() to create an object of that type.
class Student : Model.Student, IHeadRepository<TEntity> where TEntity : class
The generic type constrait always belongs to the type definition, so in your case, the where TEntity : class belongs to the definition of class Student. But since Student is not a generic type, you cannot have a generic type constraint.
Instead, you want Student to implement the generic type IHeadRepository<TEntity> (which has that constraint), so you will have to figure out what generic type you want to insert in that case:
class Student : Model.Student, IHeadRepository<SomeFoo>
{ }
In that case SomeFoo is required to follow the constraint of TEntity, i.e. SomeFoo needs to be a reference type. But what you want to insert there depends on what the interface actually means and how Student is supposed to implement it.

Prefix T is not important, but as you pointed out, it is a convention generally followed. You may note that one may have generic classes with <T,U>, or <TKey,TValue>.. just depends on what makes most sense in the context to you.
where TEntity : class This line tells the compiler, that you expect the generic type <TEntity> to be only reference types. And not value types. For example, if you said `HeadRepo, compiler will not allow it.
Typically when you want to add functionality to EF generated entity classes, you do not extend them (you could, in certain scenarios), but the classes generated by EF framework are partial classes.. Hence you could just declare your models partial class in another file, where you could add additional properties and methods etc.. This way EF will recognize your model class vs it not having any awareness of your new derived class.
The problem with the code public partial class Student : Model.Student, IHeadRepository<TEntity> where TEntity : class, is that while you are declaring a concrete class student, you are implementing a Generic Interface on it.. That doesn't make sense, because a concrete class must be concrete, and on contrary, you are making it implement a Generic interface, without specifying concrete type for TEntity. Like I said, extending Model.Student is not the right approach here..
Do not declare a new Student class.. You want to create a partial class for the same same Student class, as defined in your Model namespace.

Constraints
where TEntity : class
means that TEntity has to be a class. Otherwise it might be a struct or something else.
Inheritance with constraints
public partial class Student : IHeadRepository<TEntity> where TEntity : class
If you want to use constraints here you have to do like
public partial class Student<TEntity> : IHeadRepository<TEntity> where TEntity : class
Otherwise you have to use a concrete class without any constraints like
public partial class Student : IHeadRepository<YOURCLASS>
Of course YOURCLASS has to meet the constraint and therefore must be a class.

Related

can any one explain the hierarchy tree public interface IGenericRepository<T> where T: class?

we write the code and when we will use generic repo pattern but can anyone explain this convention please? so can anyone explain this code so we can understand how this inheritance works.
public interface IGenericRepository < T > where T: class
This is not inheritance; it is a Type Constraint.
It limits your developers to not use classes in your Generic Repository that are not an actual representation of a DB object.
Imagine, that all your mapped entities implement an Id field of type Guid. You can constraint your repositories to only be usable with objects that have that Id:
public interface IEntity
{
public Guid Id
}
public interface IGenericRepository < T > where T: IEntity
Your Generic Repo will be limited to types which implement that specific interface, and you would be sure that all concrete implementations have Guid Id property.
There is no inheritance happening in public interface IGenericRepository<T> where T : class.
where T: class is a generic constraint requiring T to be a reference type (non-nullable reference type since C#8 within nullable context):
where T : class - The type argument must be a reference type. This constraint applies also to any class, interface, delegate, or array type. In a nullable context in C# 8.0 or later, T must be a non-nullable reference type.
i.e. you can't create for example a IGenericRepository of int (IGenericRepository<int>) cause it will not compile, but you can create repository for example of some custom class - IGenericRepository<MyClass>. Quite often such restriction comes from repos build on top of EF Core (though some would argue that using generic repository pattern with EF is actually antipattern), cause it requires entity types to be constrained to class.
Related:
Generic type parameters
Generic interfaces
Constraints on type parameters
Value Types and Reference Types

C# inheritance template and caste

it's my first question, excuse my incompetence,
I am trying to declare an object that is created from the inheritance of the same class but it tells me that I cannot cast the object being inherited
abstract class BaseEntity{...}
abstract class BaseController<T> where T : Model.BaseEntity{...}
class DummyEntity : BaseEntity {...}
class DummyController : BaseController<DummyEntity> {...}
When I want to create an object, it indicates that it cannot be implicitly converted.
BaseController<BaseEntity> a = new DummyController();
You cannot do that. This has something to do with covariance.
Imagine the BaseController<T> has a method Add(T entity).
Now you create an instance of DummyController. You can call Add(CowEntity entity) on this instance because DummyController inherits BaseController<CowEntity> so T is CowEntity.
Now if you were able to assign this to BaseController<BaseEntity> you would suddenly be able to call Add(BaseEntity entity) (because T is now BaseEntity, not CowEntity anymore).
This means you could add an instance of ChickenEntity (which has nothing to do with CowEntity, it's just another derived class of BaseEntity) to that base-controller which is actually an instance of BaseController<CowEntity>. Now suddenly an instance of BaseController<CowEntity> contains a ChickenEntity. You see that this doesn't make sense.
To solve this you need to read about interfaces and covariance (and contravariance).
Hope this helps :)

C# - Is there a way to inherit from a generic class with dynamic types

I have a repository generic class that handle database operations with Entity Framework.
I want to inherit from this class, but I want this derived class to use different type of table datatypes.
For example, if the base class is called Repository<TEntity, TContext> and I want to inherit from it this way class : Repository<TableTB, someDBContext>.
Let's say I have more than one table (TableTB and TableTB2) and more than one DBContext (someDBContext1 and someDBContext2) and I want my class to inherit once from
class : Repository<TableTB, someDBContext1>
and once from
class : Repository<TableTB2, someDBContext2>
I am not sure if I was able to describe my problem good enough. so tell me what can I add to clarify more.

Trying to identify used pattern/paradigm (using C#)

While working on a particular design for a object heirarchy I came up with a situation, and built a design that works, but it's pretty confusing pattern in use, and I wanted to check if anyone had seen this pattern before and if there was any literature on it:
So imagine you have a Heirarchy of Animals:
class Animal
class Mammal : Animal
class Dolphin : Mammal
Now imagine we have an interface:
interface IMating<T>
{
MateWith(T otherAnimal);
}
In this instance I'm using generics to strongly type the MateWith method. I could just use object and do some casting which could be unsafe, but I chose to strongly type things.
Given this interface what I ideally would want is:
class Animal : IMating<Animal>
{
}
class Mammal : Animal, IMating<Mammal>
{
}
class Dolphin : Mammal, IMating<Dolphin>
{
}
Doing this allows the derived IMating.MateWith method to extend it's parents behavior by use the base versions of these classes. Of course this means if I were to use an instance of Dolphin I would land up with the following methods on Dolphin:
Dolphin.MateWith(Animal a);
Dolphin.MateWith(Mammal m);
Dolphin.MateWith(Dolphin d);
Obviously I only want the last method in that list, and I want the others hidden from access and just used up the base chain (Animal and mammal are not abstract in my case and can be instantiated). One alternative is to make use of composition thus abstracting the inner "base" class under use.
Since this felt more like a heirarchy that lends itself to inheritance I solved my problem using generic constraints as follows (with some side effects):
class Animal<T> : IMating<T>
where T : Animal
{
}
class Mammal<T> : Animal<T>
where T : Mammal
{
}
class Dolphin<T> : Mammal<T>
where T : Dolphin
{
}
Basically I'm making each class in heirarchy generic but at mininum the type parameter must be at least of the type of the class itself or any derived version of that class.
The pattern for the most part solves what I'm trying to achieve, but I'm wondering if this kind of pattern is used anywhere else and what for? Is it documented somewhere? Is it well known?
Thanks in advance for any help/pointers

Using generics in a business object and collection

I have a base object abstract class and a base object collection class for some business objects to inherit from. I'm trying to figure out how to pass the base object type to the collection class (and other methods). I've been able to solve this by wrapping the class in an interface but i'm wondering if there is another way to do this or if using an interface is the best way. i think my question might make more sense from the code below.
i have a base class define -
public abstract class BaseObject<TYPE,KEY>:where TYPE:BaseObject<TYPE,KEY>, new()
public KEY ObjectId {get;protected set; }
i have a class that inherits from BaseObject
public class Customer : BaseObject<Customer,Guid>
My base collection class is -
public abstract class BaseObjectCollection<T> : List<T> where T: BaseObject, new()
I also have a few methods in other class that want to reference this baseclass -
public bool ValidateRule(BaseObject dataObject) {etc...}
If you use the base class in other classes that are not also generics, then I'm afraid that you're going to have to specify the type and key parameters for the object when you pass it to methods like ValidateRule.
In this design, an Interface implemented by the base object is probably the most appropriate solution. We use this pattern extensively in our code and it works quite well.
One other item you could explore is reducing the complexity of the base class slightly by moving the Key into the class as an overridable (or must override) property that defaults to a string or int or whatever may be appropriate. We found that this approach (we forced all collection keys to be strings) significantly reduced the class complexity.

Categories