#c# #linq #types
#c# #linq #типы
Вопрос:
Допустим, у нас есть некоторые типы, определенные как so:
public class BaseClass
{
public int Value { get; set; }
}
public class SubClassA : BaseClass
{
public bool SomeBoolValue { get; set; }
}
public class SubClassB : BaseClass
{
public decimal SomeDecimalValue { get; set; }
}
И мы создаем два списка типа подкласса следующим образом
List<SubClassA> subClassAList = new List<SubClassA>
{
new SubClassA {SomeBoolValue = true, Value = 0},
new SubClassA {SomeBoolValue = true, Value = 2},
new SubClassA {SomeBoolValue = false, Value = 1},
};
List<SubClassB> subClassBList = new List<SubClassB>
{
new SubClassB {SomeDecimalValue = 1.3M, Value = 2},
new SubClassB {SomeDecimalValue = 3.5M, Value = 1},
new SubClassB {SomeDecimalValue = 0.2M, Value = 5},
};
Есть ли способ реализовать функцию, которая может фильтровать как subClassAList, так и subClassBList по свойству Value?
Я знаю, что это может быть достигнуто путем приведения результатов функции следующим образом:
public static IEnumerable<BaseClass> OrderList(IEnumerable<BaseClass> list)
{
return list.OrderBy(x => x.Value);
}
...
...
orderedAList = OrderList(subClassAList)
.Cast<SubClassA>() //Don't like requiring a cast. Unsafe.
.ToList();
Но тогда нам нужно привести результаты, чтобы вернуть их обратно в список подклассов, который не кажется очень безопасным для типов. Я знаю, что операция упорядочения сама по себе очень проста и, вероятно, не требует отдельной функции для выполнения действия, но если вы пытаетесь сделать что-то более сложное, чем упорядочивание, было бы полезно содержать логику в одной функции / классе / что угодно, чтобы добиться этого, а нечем копирование кода.
Комментарии:
1. Почему бы просто не вызвать
.OrderBy(x => x.Value)
список? Если вы вызываете его в aList<SubClassA>
, он возвращает перечислимоеSubClassA
значение, если вы не приведете его кBase
списку, верно?2. Потому что, если бы вы хотели упорядочить список A и список B, вам пришлось бы писать код
OrderBy(x => x.Value)
дважды. Честно говоря, если это просто упорядочивание, это не составит большого труда, но я ищу решения этой небольшой проблемы, чтобы я мог получить идеи о том, как экстраполировать ее на операции, которые были бы более сложными, чем упорядочивание, и требуют нескольких шагов
Ответ №1:
Вы могли бы выполнить это с помощью универсального метода.
public static IEnumerable<T> OrderList<T>(IEnumerable<T> list) where T : BaseClass
{
return list.OrderBy(x => x.Value);
}
Комментарии:
1. Спасибо, это то, что мне было нужно. Я просто применил его к более сложной функции фильтрации, которую я использовал, и она работает хорошо.
Ответ №2:
Вы можете использовать универсальный класс для решения этой проблемы, как показано ниже:
class LinqUtil<T> where T : BaseClass
{
static void MyMain()
{
List<SubClassA> subClassAList = new List<SubClassA>
{
new SubClassA {SomeBoolValue = true, Value = 0},
new SubClassA {SomeBoolValue = true, Value = 2},
new SubClassA {SomeBoolValue = false, Value = 1},
};
List<SubClassB> subClassBList = new List<SubClassB>
{
new SubClassB {SomeDecimalValue = 1.3M, Value = 2},
new SubClassB {SomeDecimalValue = 3.5M, Value = 1},
new SubClassB {SomeDecimalValue = 0.2M, Value = 5},
};
IList<SubClassA> orderedAList = LinqUtil<SubClassA>.OrderList(subClassAList)
.ToList();
IList<SubClassB> orderedBList = LinqUtil<SubClassB>.OrderList(subClassBList)
.ToList();
}
public static IEnumerable<T> OrderList(IEnumerable<T> list)
{
return list.OrderBy(x => x.Value);
}
}
Ответ №3:
Вы должны добавить интерфейс для этого класса следующим образом:
public interface IBaseClass
{
int Value { get; set; }
}
ublic class BaseClass:IBaseClass
{
public int Value { get; set; }
}
public class SubClassA : BaseClass,IBaseClass
{
public bool SomeBoolValue { get; set; }
}
public class SubClassB : BaseClass,IBaseClass
{
public decimal SomeDecimalValue { get; set; }
}
И теперь вы можете легко фильтровать как subClassAList, так и subClassBList по свойству Value.
public static IEnumerable<IBaseClass> OrderList(IEnumerable<IBaseClass> list)
{
return list.OrderBy(x => x.Value);
}
orderedAList = OrderList(subClassAList)
.ToList()
Комментарии:
1. Разве это не похоже на приведенный мной пример? Функция orderList просто выдаст перечисление IBaseClass вместо BaseClass . Результат все равно нужно будет привести обратно к типу списка подклассов, чтобы работать с ним как со списком подклассов или подклассовb
2. но это безопасное приведение
3. все еще есть повышающая обработка в случае, если вы используете универсальный метод