Inverting a generic constraint [duplicate] - c#

This question already has answers here:
generic NOT constraint where T : !IEnumerable
(7 answers)
Closed 5 years ago.
I've been heavily learning generic constraints the last week. While learning them more in depth, I became curious if it's possible to invert them in some way. The people I work with aren't sure that such a thing exists and my google searching has also come up with nothing.
The closest answer I got was to use struct instead of class, but while I can see why the person thought this was a decent answer and would work for most of the uses, it still doesn't answer if there is a way of inverting the constraint.
Does anyone else know if it's possible to invert a constraint?
e.g.
class myClass<T> where T: !class
{
}

No, there is no such syntax in C#.
From MSDN:
The following table lists the six types of constraints:
where T: struct The type argument must be a value type.
Any value type except Nullable can be specified. See Using Nullable
Types for more information. where T : class The type argument must be
a reference type; this applies also to any class, interface, delegate,
or array type.
where T : new() The type argument must have a public
parameterless constructor. When used together with other constraints,
the new() constraint must be specified last.
where T : (base class name) The type argument must be or derive from the specified base
class.
where T : (interface name) The type argument must be or
implement the specified interface. Multiple interface constraints can
be specified. The constraining interface can also be generic.
where T : U The type argument supplied for T must be or derive from the
argument supplied for U.
So there is no option to say where T is any type other than U
Think about it this way - suppose you had
class myClass<T> where T: !string
{
}
You know T is not a string, but you have no other indication of what T might be. So how do you code against it? These would all be valid delcarations:
var x1 = new myClass<int>();
var x2 = new myClass<object>();
var x3 = new myClass<DateTime>();
var x4 = new myClass<DataTable>();
What code could you have that applies to all of these types, but would be invalid for string?

Related

Generic classes confusion in c# [duplicate]

This question already has answers here:
In C#, What is <T> After a Method Declaration?
(4 answers)
Closed 7 years ago.
What is TProperty in c#?
I saw a code like this:
public abstract class Myclass<T, TProperty> : ....
I know that T is a generic type for the type we are passing. Is TProperty also the same as T.
Anything inside the <> is a generic type indicator. It's name does not make any difference to the compiler, but it should be meaningful for code readability.
Just like in Dictionary<TKey, TValue>.
Of course it has to be unique to it's scope, inclusive of variable names in that scope.
Note that type indicators are not variables, but the Do collide with variable names (Thank you Aravol for your comment on that).
TProperty is a second generic parameter.
Like object parameters on methods, the names have to be unique to distinguish them
Generics can have more than one parameter
According to the C# language spec, any number - see Tuple<T1...T7, TRest> for eaxmple.
By convention, generic parameter names either are or start with a capital "T".
From the description of the class you provide:
public abstract class Myclass<T, TProperty> : ....
It appears the person who created the class intends for an object (T) and an object property (TProperty) to be supplied whenever creating the class.
A best guess would be something like this:
var mine = new Myclass<Generic.List, String>();
It is hard to tell without any more code or the context of how the code is used, though.

Generic classes - when to use and why

i understand what they are, I'm just wondering when is the best time to use them.
My first thought was - when we are building a (static) utility class which should perform certain operations on different data types.
Ergo, it is a good practice to use generic methods to avoid numerous overloads of a certain method? Please comment on this.
I have a small example class. It's just for the sake of an example.
public static class Math<T> where T : operator +, operator -
{
public static T Add(T a1, T a2)
{
return a1+a2;
}
public static T Subtract(T a1, T a2)
{
return a1 - a2;
}
}
Would this be a good usage of generic classes and methods, e.g I wish to add and subtract ints, doubles.. etc.. with the minimum amount of code ?
Why won't this compile? I've tried this as well as modifying the class signature:
public static class Math<T> where T : struct
I understand that I must specify whether the Type parameter is of reference or of value type.
I did that by specifying that T must be constrained as a value type, so why am I still getting error that the operator + and/or - cannot be applied to T (which should specifically be a value type)
No this wouldn't be a good use. Generics are to provide type-safe data structures without knowing the type. Generic constraints allow you to specify some semantics about the type, such as implementing an interface, having a default constructor, or being a class or struct.
Please see these MSDN articles:
An Introduction to C# Generics
Constraints on Type Parameters
.
It won't compile because the operator + parts are not valid constraints.
Being a value type does not infer operators such as + or -, it only infers value-type semantics (inherits object, is a value type, cannot be null, has a default constructor).
Generic Constraints
Generic constraints help the compiler give you more from your T. An unconstrained generic can only be proven to be object, so you only get access to object members on the argument.
If you state: public void Foo<T>() where T : new()
The compiler can prove that your type has a default public parameterless constructor. This is the purpose of constraints, it forces the types that can be party to the generic to conform to a contract.
There are various constraints, but as you have found there are some limitations. Interestingly, there are limitations in C# that do not exist in IL, as explored by Jon Skeet in his Unconstrained Melody library that exposes enum constraints to C#.
As written by others the operator+ isn't a valid constraint. If what you want is to make some generic math, you can use something like:
public static class Add<T>
{
public static readonly Func<T, T, T> Do;
static Add()
{
var par1 = Expression.Parameter(typeof(T));
var par2 = Expression.Parameter(typeof(T));
var add = Expression.Add(par1, par2);
Do = Expression.Lambda<Func<T, T, T>>(add, par1, par2).Compile();
}
}
public static class Math<T>
{
public static T Add(T a1, T a2)
{
return Add<T>.Do(a1, a2);
}
This will create and compile an Expression that does the operation and then cache it in a generic static class.
Sadly with this method you lose the static checking of you compiler (you could do something like:
object res = Math<object>.Add(new object(), new object());
and it would compile correctly. At runtime it would explode.)
In general you can't make a constraint asking for a specific method (static or non-static) or a specific property to be present (operators are like static methods) (with a single exception: the new() constraint that asks for a public parameterless constructor). What you can ask is for an interface to be implemented, or for a base class to be present, or for the generic parameter to be a class or a struct (where the two must be meant as "reference type" and "value type", and not simply as class and struct). Sadly there are no interfaces IAddable, ISubtractable, ... and even if you built them, int, double... wouldn't implement them, and to make it worse, in .NET you can't have generic specializations (a trick of C++ where you define a generic Math<T> and then you define special "cases" explicitly, like Math<int>, Math<double> and so on)
The obvious use case for generic classes is data structures which can then store any type of data without having to treat it all as instances of object. You probably use these all the time - IList<T>, IDictionary<K, V> etc. It lets you store things where you don't know the type when you're writing the structure while retaining type safety. The trick being that you also don't know anything about the type you're storing so you can't do much with it.
Thus generic constraints, which let you say something is a reference type or a value type, or has a parameterless constructor, or implements an interface. These come in useful when you're writing a generic class which has to do something with instances of the parameterised type. Might seem useless - why not just use an interface type as the parameter type and avoid generics altogether? Because generic constraints can force a parameter to conform to more than one interface - something you can't specify in a normal parameter type. Thus you can write a function:
public static void Frobnicate<T>(T thing)
where T : IList<int>, IDisposable
{
// ...
}
You can also stick a single base class name in there too. This is far, far more flexible than specifying concrete types. Sure you could create an interface which inherits from IList<int> and IDisposable but you can't retrofit all disposable lists of integers that might be out there to implement it.
You could also do it at runtime using reflection to inspect things, but this kind of thing is far better handled by the compiler, IMO.

Class syntax with <TypeParameter> C# [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does “T” mean in C#?
What does <T> denote in C#
I have searched about the question, but because I do not have any idea about that syntax, I could not search well enough. Well, after the short explanation my question is :
While I was looking to a particle effect library I meet this :
[Serializable]
public class DPSF<Particle, Vertex> : IDPSFParticleSystem
where Particle : global::DPSF.DPSFParticle, new()
where Vertex : struct, global::DPSF.IDPSFParticleVertex
{
// constructors, methods, parameters here ...
}
What does this notation mean in blankets (<...>) and how it is used ?
They are generic types that you can pass into a class definition:
A simple example:
public class Test<T>
{
public T yourVariable;
}
Test<int> intClass = new Test();
Test<string> stringClass = new Test();
intClass.yourVariable // would be of type int
stringClass.yourVariable // would be of type string
Where T is the type you want (i.e. another class, a string, integer, anything generic)
where Particle : global::DPSF.DPSFParticle - means that the Particle object must inherit from DPSF.DPSFParticle
It means that DPSF class is a generic class. Particle and Vertex between <> are type parameters. It means that DPSF gets two types as parameters and serves as a generic class.
Take a look at here: MSDN: Generics
EDIT
Where keyword allows you to restrict type parameters. where:class means parameter must be a class in order this generic class to work.

How to specify types not allowed in a .NET Generics constraint?

Is it possible to specify a constraint on a generic class that disallows certain types? I don't know if it is possible and if it is, I am not sure what the syntax would be. Something like:
public class Blah<T> where : !string {
}
I can't seem to find any notation that would allow such a constraint.
The closest you can get is a run-time constraint.
Edit: Originally I put the run-time check in the constructor call. That's actually not optimal, as it incurs overhead on every instantiation; I believe it would be much more sensible to put the check in the static constructor, which will be invoked once per type used as the T parameter for your Blah<T> type:
public class Blah<T> {
static Blah() {
// This code will only run ONCE per T, rather than every time
// you call new Blah<T>() even for valid non-string type Ts
if (typeof(T) == typeof(string)) {
throw new NotSupportedException("The 'string' type argument is not supported.");
}
}
}
Obviously not ideal, but if you put this constraint in place and document the fact that string is not a supported type argument (e.g., via XML comments), you should get somewhere near the effectiveness of a compile-time constraint.
No, you can't directly specify "negated" type constraints.
Constraints can only be positive constraints, as outlined in the documentation.
The only thing you can do is specify what types can be put into the generic type, but you cannot specify what can't be put into them.
Here are the allowed constraints (more detail)
where T: struct
where T : class
where T : new()
where T : [base class name]
where T : [interface name]
where T : U (The type argument supplied for T must be or derive from the argument supplied for U)

Can C# generics have a specific base type?

Is it possible for a generic interface's type to be based on a specific parent class?
For example:
public interface IGenericFace<T : BaseClass>
{
}
Obviously the above code doesn't work but if it did, what I'm trying to tell the compiler is that T must be a sub-class of BaseClass. Can that be done, are there plans for it, etc.?
I think it would be useful in terms of a specific project, making sure a generic interface/class isn't used with unintended type(s) at compile time. Or also to sort of self-document: show what kind of type is intended.
public interface IGenericFace<T> where T : SomeBaseClass
What your are referring to is called "Generic Constraints". There are numerous constraints that can be put on a generic type.
Some basic examples are as follows:
where T: struct - The type argument must be a value type. Any value type except Nullable - can be specified. See Using Nullable Types (C# Programming Guide) for more information.
where T : class - The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.
where T : new() - The type argument must have a public parameterless constructor. When used together with other constraints, the new() constraint must be specified last.
where T : <base class name> - The type argument must be or derive from the specified base class.
where T : <interface name> - The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.
where T : U - The type argument supplied for T must be or derive from the argument supplied for U. This is called a naked type constraint.
These can also be linked together like this:
C#
public class TestClass<T> where T : MyBaseClass, INotifyPropertyChanged, new() { }
public interface IGenericFace<T> where T : SomeBaseClass
VB
Public Class TestClass(Of T As {MyBaseClass, INotifyPropertyChanged, New})
Public Interface IGenericInterface(Of T As SomeBaseClass)
yes.
public interface IGenericFace<T>
where T : BaseClass
{
}

Categories