Общее ограничение для ValueTypes, Strings и Nullable of ValueTypes - PullRequest
6 голосов
/ 08 апреля 2009

Я пытаюсь добавить ограничение к универсальному методу, чтобы он проверял типы значений ValueTypes, Strings или Nullable.

Проблема в том, что:

  • значения типа являются распорками
  • строки являются неизменяемыми ссылочными типами
  • nullable являются типами значений, но не будут приняты в ограничении типа "where S: struct".

Так кто-нибудь знает, есть ли способ, которым я могу принять их и только эти типы в общем ограничении?

Проблема в том, что я пытаюсь принять параметр Expression<Func<T, S>, который будет представлять свойство этих типов для данного объекта.

Функциональность может быть примерно такой (обратите внимание, что код не имеет никакого смысла, и это просто что-то быстрое, чтобы понять, что я ищу):

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

Должны быть приняты все три вышеуказанных вызова, но не следующие:

MyGenericMethod(myPerson, p => p.CurrentCar); //S would be a class and shouldn't compile

Заранее спасибо

ОБНОВЛЕНИЕ: Спасибо Антон и Марк. MyGenericMethod имеет 4 разных подписи, принимающих дополнительные параметры, поэтому мне не нравится идея создания 3 разных (struct, nullable, string) для каждого из существующих 4 ... это было бы кошмаром для обслуживания!

1 Ответ

7 голосов
/ 08 апреля 2009

Единственное, что я могу придумать, это набор из трех функций (без Expression<> вещи):

MyGenericFunction<T>(T t)
    where T : struct

MyGenericFunction<T>(T? t)
    where T : struct

MyGenericFunction(string s)

ОБНОВЛЕНИЕ Учитывая, что существуют различные перегрузки метода, я могу предложить:

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
}

Таким образом, ваш метод становится

MyGenericMethod(Holder h);

Все еще очень громоздко, но, тем не менее, это может сработать.

...