Получают ли типы, которые поддерживают реляционные операторы, определенный интерфейс? - PullRequest
1 голос
/ 09 сентября 2011

У меня такое чувство, что после прочтения документации ответ - нет.Однако я пытаюсь выяснить, возможно ли узнать, поддерживает ли тип реляционные операторы, такие как: <,>,> = etc ...

Я ищу что-то вроде:

Func<MyObject, object> greaterThan = obj => obj > 10;
var results = myList.Where(greaterThan).ToList();

Поскольку я могу искать по разным свойствам, это может быть десятичное число, целое число или число с плавающей запятой.Я делаю это в действии MVC, поэтому, насколько я знаю, он не может поддерживать дженерики.Я, очевидно, могу переместить его и получить универсальную реализацию, но я хотел бы сначала узнать этот ответ.

Чтобы уточнить, неявная перегрузка операторов невозможна.Причина в том, что свойство не известно до времени выполнения (извините, я должен был упомянуть).Следовательно, и дженерики не могут быть использованы.Для любого свойства мне нужно убедиться, что оно не равно 0. Это несколько надуманный пример моей текущей реализации, которая работает (не полностью протестирована):

Func<MyObject, IComparable> prop = obj =>  isOn ? obj.DecimalVal : obj.IntValue;
Func<MyObject, bool> clause = obj => prop(obj).CompareTo(0) != 0;
var results = myList.Where(clause);

Я просто надеюсь, что CompareToвернет 0;даже если реквизит оценивает десятичное число со значением 0 по сравнению с int 0 - несмотря на то, что это разные типы.

ОБНОВЛЕНИЕ

У меня явно были слишком большие надежды, вышеуказанный подход не удался.Поэтому решение, которое я использую сейчас, нежелательно, но оно работает.Я хотел бы услышать более элегантный подход.

Func<MyObject, dynamic> prop = obj =>  isOn ? obj.DecimalVal : obj.IntValue;
Func<MyObject, bool> clause = obj => prop(obj) != 0;
var results = myList.Where(clause);

Ответы [ 4 ]

3 голосов
/ 09 сентября 2011

Нет.В C # операторы являются статическими членами типов, поэтому они не могут быть частью интерфейса.

Существует один способ работы вашего кода в C # 4: dynamic:

Func<dynamic, bool> greaterThan = obj => obj > 10;
var results = myList.Cast<dynamic>().Where(greaterThan).ToList();

Это будет работать независимо от того, является ли myList набор int с, double с или decimal с.(Но будьте осторожны, results имеет тип List<dynamic>.)

Но .Net фактически предоставляет некоторые интерфейсы, которые могут использоваться для тех же целей, которые обычно используются для операторов: сравнение на равенство (IEquatable<T>)и сравнение того, какой элемент больше, а какой меньше (IComparable<T>).С их помощью вы можете написать такой код:

static IEnumerable<T> GreaterThan<T>(this IEnumerable<T> collection, T item)
    where T : IComparable<T>
{
    return collection.Where(x => x.CompareTo(item) > 0);
}
2 голосов
/ 09 сентября 2011

Как насчет использования IComparable<T> IEqutable<T> интерфейсов.Они предназначены для общего сравнения объектов.

1 голос
/ 09 сентября 2011

Здесь вы можете использовать неявную перегрузку операторов .Я также рассмотрел бы ответ @ gmamaladze об использовании IEquatable для реализации равенства и IComparable для сравнений для сортировки, хотя тоже.

0 голосов
/ 09 сентября 2011

Нет, они этого не делают.Для поддержки таких операторов, как < > >= <=, вы явно определяете операторы в своем классе. Перегрузка оператора .

Вы также можете определить неявное приведение в ваших классах.Это позволит вам неявно приводить ваш объект к целевому типу, а затем выполнять математические операции. Эта статья может показаться вам полезной.

...