Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic constraint to ValueTypes, Strings and Nullable of ValueTypes

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:

  • value types are struts
  • strings are immutable reference types
  • nullable are value types but won't be accepted in a "where S : struct" type constraint.

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!

like image 778
antonioh Avatar asked Apr 08 '09 08:04

antonioh


People also ask

What are the constraints in generics?

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.

How to restrict generic class in c#?

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.

How do you pass the generic null?

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.

What is generic constants in c#?

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.


1 Answers

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.

like image 194
Anton Gogolev Avatar answered Oct 08 '22 17:10

Anton Gogolev