Real-world examples with subtyping constraints in .NET generics - c#

Are there any real-world examples of using subtyping constraints on type parameters in .NET generics? By «subtyping constraints» I mean
where T : <base class name>
and
where T : U
May be there are some standard generics with corresponding constraints? Or specialized generic .NET-libraries.
UPD There are lots of good examples with interface constraints
where T : <interface name>
But subtyping constraints seems to be very specific and not so useful. I try to understand, in which cases this kind of constraints is really crucial. Luaan's answer contains examples with where T : <base class name> from ASP.NET MVC, but I am still interested in real-world examples with where T : U constraint.

I use them for a repository class in my data access layer e.g.
public interface IRepository<T>
where T : IDbItentity
{
IList<T> GetAll();
T GetById(int id);
int Insert(T saveThis);
void Update(T updateThis);
void Delete(T deleteThis);
}
Where IDBItentity is an interface as follows:
public interface IDbItentity
{
int Id { get; }
}

It's something you use a lot. In a way, it immitates the way normal inheritance works.
So for example, if you've got a common functionality built around O/RM entities, you can just create an entity base class, and use that as a type constraint in all the various data layers manipulating that entity.
Extremely useful is its use with interfaces.
And very often, you're going to write some kind of a wrapper around something else.
The basic idea is that you use those when you really only want the type parameter to fit some use case, but rather than just using the interface, you let the user of your code supply their concrete type. It still implements all the stuff you need to work correctly, but at the same time, the user can use all the features, even those you don't know about.
You will not find many cases in the BCL. Basically, this has to do with the fact that type constraints are constraints. The BCL usually uses generic types and methods to write very general functionality - I guess that's in part because of the fact that most of the BCL was there before generics, and because most of the time, inheritance will work just as well, if not better.
There's still differences, though. Say you need a collection of some entities. If you just use List<Entity>, you're saying "I expect any entity whatsoever, thanks". If you use List<T> where T : Entity (pseudocode), you're saying "I need to know the type you're giving me is an Entity, but I only want one kind of entity in the whole collection".
All in all, if you want good applications of generic type constraints, look at newer code. For example, in ASP.NET MVC, there's things like this:
public abstract class CachedAssociatedMetadataProvider<TModelMetadata>
: AssociatedMetadataProvider
where TModelMetadata : ModelMetadata
public class DataAnnotationsModelValidator<TAttribute>
: DataAnnotationsModelValidator
where TAttribute : ValidationAttribute
It's also very useful when you're using Actions (or events) to tag functionality to some such general class from the outside.
Again, the uses are basically such:
Constraint the types that can be used in your class
Ensure the type passed to you conforms to some contract
Improve useability for the users of your code
Performance optimization of value-types, mostly avoiding boxing - e.g. you can use IComparable without having to box the value

Often it is used for extension methods, for example:
public static string Parse<Tenum>(this object spr, int id) where Tenum : struct, IConvertible
{
Contract.Ensures(typeof(Tenum).IsEnum, "type must be is enum");
return ((Tenum)(object)id).ToString();
}
string ProductTypeTitle = this.Parse<ProductType>(product.ProductTypeID);

Related

C# Inherited Open Generics Compile

Today my brain went dead, and I couldn't figure out a clean way of forcing the compiler to use inheritance for Generic inference.
Imagine the following 4 classes
Models
public abstract class Model
{
}
public class CodePerfModel : Model
{
}
Entities
public abstract class ModelEntity<TModel> where TModel : Model
{
public TModel Model { get; set; }
}
public class CodePerfEntity : ModelEntity<CodePerfModel>
{
}
Now to me logically I should take for granted that when I take something that inherits from ModelEntity<> (it will specify the type of TModel) via inheritance, because any class that inherits from ModelEntity<> will have to specify it.
Is there anyway to force the compiler to figure this out for me?
E.g.
If I currently want to use ModelEntity<>, I have to specify a type for it. Such as the following:
public class CallerClass<TEntity, TModel>
where TEntity : ModelEntity<TModel>
where TModel : Model
{
}
How can I get rid of the TModel argument everywhere? While still having access to the TModel type at compile time? E.g. via the base Model property.
To me, something like the following:
public class CallerClass<TEntity>
where TEntity : ModelEntity<>
{
}
Would make perfect sense as when calling it all I should have to speicfy is e.g.
SomeCall<CodePerfEntity>();
rather than
SomeCall<CodePerfEntity, CodePerfModel>();
Is this something that is currently possible?
Would this be worth raising for C# 6/7?
You mention you would like to access TModel at compilation time, while not explicitly specifying this type when deriving a class. Letting go of your example, and moving to a more general case, this means you would like the semantics to remain the same, however you would not like to explicitly declare the type parameter's own type parameters when declaring a generic constraint.
In essence, you are asking why a specific syntax sugar feature is not implemented.
Let's consider another example:
public class CallerX<A, B> where A : ModelEntity<> where B : ModelEntity<>
From the example in your question, the compiler should insert TModel'1 and TModel'2 as type parameters for A and B respectively. Let's say the feature is implemented. This means that we have created the default situation that TModel'1 and TModel'2 are different types, each having constraints that match the single type.
What if I would like to add more constraints to either TModel'1 or TModel'2, or force them to be the same type? Why is this case so special that it deserves its own syntax?
From what I know of the C# team, they have the policy that each new feature starts with "-100 points" and should be really great in order to be considered (see UserVoice for C#).
To summarize:
New language features are expensive and add complexity.
You are asking for an implicit syntax for which it is unlikely/unclear that it will be the desired situation in most of the cases.
Developers will have to learn and understand that an open generic type as a type parameter constraint will insert a hidden and anonymous extra parameter. To me, it is not intuitive that some other type parameter has been added to my type without me having declared it.

Generic class with an interface constraint vs class implementing interface

Recently I was implementing a Trie data structure and decided the Nodes could store different types of data or have its implementation varied so then I went for Node<T>. Then as I got into the algorithm for constructing the Trie I realised it required more intimate knowledge of the Node so I constrained the generic class to use an INode interface. This allows for more flexibility but felt wrong in the context of a generic class.
Generic classes have a different use case to classes which implement an interface. For example, List<T> - the algorithm can work without being dependent on a related set of abstractions. A class which implements an interface may require polymorphism/DI but the interfaces will be more specialized.
Under what circumstances do others apply a generic class T where T may implement a more specialized interface?
I thought that a generic class is used when T does not really need to expose operations/data though I can see a generic class may be used where T implements IDisposable or some other more general interface.
Any help in clarifying these points?
When faced with a choice to use a generic with an interface constraint vs. a non-generic with an interface type, I would go for generic+interface only in situations when some or all of types passed as generic arguments are value types. This would prevent my implementation from requiring costly boxing and unboxing when dealing with my structs.
For example, if the interface happens to be IComparable, I wold definitely prefer a generic with a constraint, because it would let me avoid boxing when working with primitives.
Note that an alternative way of providing functionality to your generic class is passing a delegate along with the value. For example, if you plan to do something like this
interface IScoreable {
decimal GetScore(object context);
}
class Node<T> where T : IScoreable {
...
void DoSomething(T data) {
var score = data.GetScore(someContext);
...
}
}
you can also do this:
class Node<T> {
private Func<T,object,decimal> scorer;
public Node(Func<T,object,decimal> scorer) {
this.scorer = scorer;
}
...
void DoSomething(T data) {
var score = scorer(data, someContext);
...
}
}
The second solution lets you "decouple" the scoring functionality from the type being scored, at the expense of having the caller to write a little more code.
I see nothing wrong with placing constraints on the generic argument. Having a generic argument does not imply "this will work for anything", it implies that there is more than one way that the code will make sense.
It might actually expose a completely generic concept, like List<T>, but it might expose a concept that makes sense only in some contexts (like Nullable<T> only making sense for non-nullable entities)
The constraints are just that mechanism that you use to tell the world under what circumstances the class will make sense, and will enable you to actually use that (constrained) argument in a reasonable way, i.e. calling Dispose on things that implement IDisposable
The extreme of this is when the context is very constrained, i.e. what if there are only two possible implementations? I actually have that case in my current codebase, and I use generics. I need some processing done on some data point, and currently (and in the foreseeable future) there are only two kinds of data points. This is, in principle, the code I use:
interface IDataPoint
{
SomeResultType Process();
}
class FirstKindDataPoint : IDataPoint
{
SomeResultType Process(){...}
};
class SecondKindDataPoint : IDataPoint
{
SomeResultType Process(){...}
};
class DataPointProcessor<T> where T: IDataPoint
{
void AcquireAndProcessDataPoints(){...}
}
It makes sense, even in this constrained context, because I have only one processor, so only one logic to take care of, instead of two separate processor that I will have to try to keep in sync.
This way I can have a List<T> and an Action<T> within the processor instead of a List<IDataPoint> and Action<IDataPoint> which will be incorrect in my scenario, as I need a processor for a more specific data type, that is still, implementing IDataPoint.
If I needed a processor that will process anything, as long as it is an IDataPoint, it might make sense to remove the its genericity, and simply use IDataPoint within the code.
Additionally, the point raised in #dasblinkenlight's answer is very valid. If the generic parameters can be both structs and classes than using generics will avoid any boxing.
Generics are usually used where using an interface or a base class (and this includes object) are not enough, for example where you are worried about the return value's of your function being the original type rather than just the interface, or where the parameters you are passing in may be expressions that operate on the specific type.
So if you approach the logic from the other end. The decisions on type restrictions should be the same decision as when you are choosing the types of your function parameters.

Empty interfaces and abstract class enforce structure

I've been looking into empty interfaces and abstract classes and from what I have read, they are generally bad practice. I intend to use them as the foundation for a small search application that I am writing. I would write the initial search provider and others would be allowed to create their own providers as well. My code's intent is enforce relationships between the classes for anyone who would like to implement them.
Can someone chime in and describe if and why this is still a bad practice and what, if any alternatives are available.
namespace Api.SearchProviders
{
public abstract class ListingSeachResult
{
public abstract string GetResultsAsJSON();
}
public abstract class SearchParameters
{
}
public interface IListingSearchProvider
{
ListingSeachResult SearchListings(SearchParameters p);
}
}
Empty classes and interfaces are generally only "usably useful" as generic constraints; the types are not usable by themselves, and generic constraints are generally the only context in which one may use them in conjunction with something else useful. For example, if IMagicThing encapsulates some values, some implementations are mutable, and some aren't, a method which wants to record the values associated with an IMagicThing might be written something like:
void RecordValues<T>(T it) where T:IImagicThing,IIsImmutable {...}
where IIsImmutable is an empty interface whose contract says that any class which implements it and reports some value for any property must forevermore report the same value for that property. A method written as indicated could know that its parameter was contractually obligated to behave as an immutable implementation of IMagicThing.
Conceptually, if various implementations of an interface will make different promises regarding their behaviors, being able to combine those promises with constraints would seem helpful. Unfortunately, there's a rather nasty limitation with this approach: it won't be possible to pass an object to the above method unless one knows a particular type which satisfies all of the constraints, and from which object derives. If there were only one constraint, one could cast the object to that type, but that won't work if there are two or more.
Because of the above difficulty when using constrained generics, it's better to express the concept of "an IMagicThing which promises to be immutable" by defining an interface IImmutableMagicThing which derives from IMagicThing but adds no new members. A method which expects an IImmutableMagicThing won't accept any IMagicThing that doesn't implement the immutable interface, even if it happens to be immutable, but if one has a reference to an IMagicThing that happens to implement IImmutableMagicThing, one can cast that reference to the latter type and pass it to a routine that requires it.
Incidentally, there's one other usage I can see for an empty class type: as an identity token. A class need not have any members to serve as a dictionary key, a monitor lock, or the target of a weak reference. Especially if one has extension methods associated with such usage, defining an empty class for such purpose may be much more convenient than using Object.

Cannot specify both a constraint class and the 'class' or 'struct' constraint

I am trying to work around a mocking issue by creating a custom mock of IDbSet.
The custom mock:
public class DbSetMock : IDbSet<Tenant>
{
/* hidden all other implemented methods/properties */
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, Tenant
{
throw new NotImplementedException();
}
}
The create method gives a build error that I have no clue on how to solve:
cannot specify both a constraint class and the 'class' or 'struct' constraint
Simply removing class from the constraints results in another build error (which I also don't understand :( ).
The constraints for type parameter 'TDerivedEntity' of method 'Tests.DAL.Tenants.DbSetMock.Create<TDerivedEntity>()' must match the constraints for type parameter 'TDerivedEntity' of interface method 'System.Data.Entity.IDbSet<BusinessLayer.DAL.Tenants.Tenant>.Create<TDerivedEntity>()'. Consider using an explicit interface implementation instead.
Can anybody help me successfully building this class?
Since the TDerived type parameter is constrained to be a Tenant, adding the constraints class or struct is redundant. Just remove the class constraint.
UPDATE: Curiously there seems to be a conflict between the compiler errors here. If you "fix" one you get the other, in an infinite loop of despair. Luckily, the second error also gives us a way out: you can use an explicit interface implementation:
public class DbSetMock : IDbSet<Tenant>
{
TDerivedEntity IDbSet<Tenant>.Create<TDerivedEntity>()
{
throw new NotImplementedException();
}
}
There seems to be no way to implement that method without using explicit interface implementation. If you need it as part of the public interface of the class, I suggest creating another method that the interface implementation forwards to:
public class DbSetMock : IDbSet<Tenant>
{
TDerivedEntity IDbSet<Tenant>.Create<TDerivedEntity>()
{
return Create<TDerivedEntity>();
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : Tenant
{
throw new NotImplementedException();
}
}
Try to remove class from method part, like this;
public class DbSetMock : IDbSet<Tenant>
{
/* hidden all other implemented methods/properties */
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : Tenant
{
throw new NotImplementedException();
}
}
class, Tenant is redundant code.
There are presently only three inheritable classes in the Framework whose descendants may be value types: Object, ValueType, and Enum. All three of those types are class types, but any type derived from ValueType or Enum will be a value type, and any type derived from Object which is not derived from ValueType will be a class type. With any type other than the above, a class or struct constraint would either be redundant or contradictory; not coincidentally, C# disallows constraints to be directly specified for the above types.
In some languages and frameworks, a prevailing design philosophy is that if there is a particular form of expression where the behavior that applies to that general form would be useless, there's no reason for the language/framework designer to go out of the way to forbid such a form. Under such a philosophy, it would be perfectly legal to have a generic type constrained to a sealed type (e.g. Fnord). Such a thing would be pointless if the type in question were sealed and no future version would ever be otherwise, but since applying the normal interpretation of generic constraints to such situation would yield reasonable behavior, and since there might conceivably be some situations where such constraints might be useful (e.g. writing code to use a class which is in development and is presently sealed, but may or may not be sealed in its final release, or writing code to interface with Reflection-based code that expects particular generic forms), the philosophy would suggest that constraining a generic type to a sealed class should be legal.
In some other languages and frameworks, a differing philosophy holds: if a programmer might expect some particular form of a construct to offer features beyond the general form but it does not, and if that particular form wouldn't seem very useful without such features, the language should forbid it, even if the construct would have a precise meaning which was well-defined and could not be expressed via other means if the implementers of the language don't see a reason for programmers to want to express that actual meaning.
The fact that neither C# nor .net has any problem with having one type parameter constrained to another, even when that other parameter is of a type that would not be accepted as a constraint, suggests that the restriction is artificially imposed by the language due to the aforementioned philosophy. It's unfortunate, IMHO, since there are many situations where it would be helpful to be able to say, e.g.
bool HasAnyFlags<T>(this T enum1, T enum2) where T:struct,System.Enum
and even though .net would usefully allow such a construct, and even though the only obstacle which prevents C# from excepting it code to explicitly looks for such constraints so as to disallow them, the C# designers decided to forbid such constructs rather than allow them to behave as .net would interpret them (meaning that HasAnyFlags couldn't do anything directly with a T that it couldn't do with System.Enum, and using a T as a System.Enum would generally be no faster than using a System.Enum (sometimes slower), but T could nonetheless be useful for a couple reasons:
The method could enforce at compile time that the parameters must be the *same* enumerated type
The method could use a static class `EnumEvaluator` to generate and cache static delegates of type `Func`, such that `HasAnyFlags(T enum1, T enum2)` could be implemented as `return EnumEvaluator.HasAnyFlags(enum1,enum2);`. Such a function could be more than ten times as fast as `Enum.HasFlag`.
Still, useful as it might be to specify such constraints, the only way to specify them in C# is to have the C# source code specify some dummy type which could be used as a constraint, and then run the compiled code through a utility which will replace all references to the dummy type with references to the type one wanted to use in the first place.
It is telling you is that the constraint:
class, Tenant
is redundant. You can just remove class since Tenant is more constrained than class and includes class.

Implementing a generic interface

I have a generic interface:
public interface IUnauthorizedRequestRespondable<out T> where T:class
{
T GetResponseForUnauthorizedRequest();
}
(I'm not sure why Resharper recommended T is "out", but that's not the question).
In my scenario, the object returned by GetResponseForUnauthorizedRequest is always of the type that implements the interface.
So all the interface's implementations look like:
public class SignInReturnedObject : IUnauthorizedRequestRespondable<SignInReturnedObject>
(class name and the type in brackets are always the same).
Which seems a bit awkward - isn't there a neater way to tell the compiler that the interface's method returns the type it's a part of?
Thanks.
As far as I know, there is no way to do that currently in C#.
A theoretical side-note: The feature that would allow you to do this is called self types but that's not available in C#. The idea of the feature is that you have a special type that refers to the actual type of this, so if you had a special type named self, you could probably write something like:
public interface IUnauthorizedRequestRespondable {
self GetResponseForUnauthorizedRequest();
}
...and the actual type used in place of self when you have a class SignInReturnedObject implementing the interface would be SignInReturnedObject, but unfortunatelly, that's not
available in C# :-)
If the only way you want to use that template is in that manner, I would use:
public interface IUnauthorizedRequestRespondable<T> where T:IUnauthorizedRequestRespondable<T>
{
T GetResponseForUnauthorizedRequest();
}
This has the advantage of guaranteeing it isn't used in any other way.
The class declaration won't change, but I don't see anything as awkward in this myself. Considering that you are defining a relationship between the class and itself, any more concise form might be inadvisable.
Actually, that about sums it up. That is how the syntax works.
You can see it used in .NET itself with the IEquatable inteface--you are almost always comparing an object to itself, yet you always have to provide your own class name as a template parameter.
This is simply to provide flexibility such that you can compare to anything, not necessarily yourself.
You can create a nongeneric version and just use that but I think it is more trouble than it is worth
public interface ICastUnauthorizedRequestRespondable : IUnauthorizedRequestRespondable<SignInReturnedObject>
{
}
Since T can be any class (does not have to be the class you are implementing) you need to name your class.
public class SignInReturnedObject : IUnauthorizedRequestRespondable<ANYCLASS>

Categories

Resources