I'm trying to add a constraint to a generic method so it checks for ValueTypes, Strings or Nullable value types.
The problem is that:
So does anybody know if there's a way I can accept these and only these types in a generic constraint?
The problem is I'm trying to accept an Expression<Func<T, S>
parameter that will represent a property of these types for a given object.
The functionality would be something like the following (note the code doesn't make any sense and is just something quick to get an idea of what I'm looking for):
public class Person
{
public string Name {get; set;}
public DateTime? DOB {get; set;}
public int NumberOfChildren {get; set;}
public Car CurrentCar {get; set;}
}
---
internal void MyGenericMethod<T, S>(T myObject, Expression<Func<T, S> property){...}
Person myPerson = new Person();
MyGenericMethod(myPerson, p => p.Name); //S would be a string
MyGenericMethod(myPerson, p => p.DOB); //S would be a DateTime?
MyGenericMethod(myPerson, p => p.NumberOfChildren); //S would be a struct
The three calls above should all be accepted, but not the following:
MyGenericMethod(myPerson, p => p.CurrentCar); //S would be a class and shouldn't compile
Thanks in advance
UPDATE: Thanks Anton and Marc. MyGenericMethod has 4 different signatures accepting extra parameters, that's why I don't like the idea of creating 3 different (struct, nullable, string) for each of the existing 4... that would be a nightmare to maintain!
The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.
You can specify one or more constraints on the generic type using the where clause after the generic type name. The following example demonstrates a generic class with a constraint to reference types when instantiating the generic class.
There is no way of specifying a null generic type argument - each generic type argument must be a valid type matching the type constraints that might exist.
In c#, generics are used to define a class or structure or methods with placeholders (type parameters) to indicate that they can use any of the types. Following is the example of defining a generic class with type parameter (T) as a placeholder with an angle (<>) brackets.
The only thing I can come up with is a set of three functions (sans Expression<>
stuff):
MyGenericFunction<T>(T t)
where T : struct
MyGenericFunction<T>(T? t)
where T : struct
MyGenericFunction(string s)
UPDATE Given that there are various overloads of a method, I can suggest:
class Holder
{
private object value;
public Holder(object value)
{
this.value = value;
}
public static implicit operator Holder(DateTime dt)
{
return new Holder(dt);
}
public static implicit operator Holder(string s)
{
return new Holder(s);
}
// Implicit conversion operators from primitive types
}
Thus your method becomes
MyGenericMethod(Holder h);
Still very cumbersome, but nevertheless it might work out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With