Во-первых, мы можем остановить переопределение функций, только если они могут быть переопределены вообще. Таким образом, final
имеет смысл только для виртуальных функций.
Тем не менее, final
, примененное к виртуальной функции одного класса, может показаться довольно бессмысленным. Но если вы рассмотрите более сложную иерархию, то материя изменится:
class Parent
{
public:
virtual ~Parent() = default;
virtual void f();
};
class Child : public Parent
{
public:
void f() final; // f IS virtual already...
};
class GrandChild : public Child
{
// cannot override f any more – while Child still could!
};
Кроме того, учтите следующее:
class Base
{
public:
virtual ~Base() = default;
void f(); // non-virtual! (i. e. cannot be overridden)
};
class Derived : public Base
{
public:
void f(); // does not override, but HIDEs Base::f!!!
};
Объявление Base::f
как виртуального, так и конечного также предотвратит сокрытие ( но не после загрузки ).
На самом деле, опять же, этот сценарий, скорее, имеет смысл, если сам Base
уже унаследован от другого полиморфного класса. Если нет и Base
не предназначен для наследования, я бы вообще не вводил никаких виртуальных функций (вызовы виртуальных функций обходятся дороже, чем обычные вызовы функций!). Если затем пользователь все еще наследует и скрывает функцию - ну, это его ответственность ...
Я нахожу LINQ к Объектам полезным повсеместно. Проблема, которую это решает, является довольно общей:
Это - ситуация, с которой я сталкиваюсь довольно часто. Существует очень много областей программирования, которые в основном включают преобразование одного набора (или поток данных) в другого. В тех случаях код с помощью LINQ почти всегда короче и более читаем. Я хотел бы указать, что LINQ не должен быть расценен как являющийся синонимичным с выражениями запроса - если только единственный оператор требуется, нормальная "запись через точку" (использующий дополнительные методы) может часто быть короче и более читаемой.
Одна из причин, которые я особенно как LINQ к Объектам - то, что это является настолько общим - тогда как LINQ к SQL, вероятно, только займется Вашим слоем данных (или в значительной степени стать слоем данных), LINQ к Объектам применим в каждом слое, и во всех видах приложений.
Так же, как пример вот строка в моем MiniBench, сравнивающем платформы, преобразовывая a TestSuite
(который является в основном именованным набором тестов) в a ResultSuite
(именованный набор результатов):
return new ResultSuite(name,
tests.Select(test => test.Run(input, expectedOutput)));
С другой стороны, если a ResultSuite
потребности, которые будут масштабироваться против некоторого конкретного "стандартного" результата:
return new ResultSuite(name,
results.Select(x => x.ScaleToStandard(standard, mode)));
Не было бы трудно написать этот код без LINQ, но LINQ просто делает это более ясным и позволяет Вам сконцентрироваться на реальной "логике" вместо деталей итерации через циклы и добавления результатов к спискам и т.д.
Даже когда сам LINQ не применим, некоторые функции, которые были в основном включены ради LINQ (например, неявно введенные локальные переменные, лямбда-выражения, дополнительные методы) могут быть очень полезными.
Ответ практически везде приходит на ум. Лучший вопрос состоял бы в том, чтобы если не использовать его.
LINQ является большим для "скользкого пути". Думайте о том, что вовлечено во многие общие операции:
Dictionary<key, List<value>>
и цикл через все объекты. Если никакой ключ не существует, создают его, то добавляют объекты к соответствующему списку. В каждом из тех случаев процедурный путь берет больше кода, чем путь LINQ. В случае того, "если" это - несколько строк больше; в случае GroupBy или OrderBy/ThenBy это намного больше.
Теперь возьмите слишком общий сценарий объединения их вместе. Вы внезапно смотрите на метод строки 10-20, который мог быть решен с 3-4 строками в LINQ. И версию LINQ, как гарантируют, будет легче считать (после того как Вы знакомы с LINQ).
Таким образом, когда Вы используете LINQ? Мой ответ: каждый раз, когда Вы видите "foreach" :)
LINQ довольно полезен в нескольких сценариях:
LINQ входит для проигрывания, когда Вы начинаете делать сложную фильтрацию на сложных типах данных. Например, если Вам дают список Людей объекты, и необходимо собрать список всех врачей в рамках того списка. С LINQ можно сжать следующий код в единственный оператор LINQ:
(псевдокод)
doctors = []
for person in people:
if person is doctor:
doctors.append(person)
(извините, мой C# ржав, введите синтаксис проверки, является, вероятно, неправильным, но Вы получаете идею),
doctors = from person in people where person.type() == doctor select person;
Править: После того, как я ответил, что вижу изменение для высказывания "LINQ Объектам". О, хорошо.
Если LINQ мы обращаемся ко всем новым типам в Системе. Linq, а также новые функции компилятора, затем это будет обладать довольно мало преимущества - это эффективно добавляет функциональное программирование к этим языкам. (Вот прогрессия, которую я видел несколько раз (хотя это - главным образом C# - VB ограничен в текущей версии).
Очевидный запуск - то, что что-либо связанное с обработкой списков становится значительно легче. Много циклов может просто уйти. Какую пользу Вы извлекаете? Вы начнете программировать более декларативно, который приведет к меньшему количеству ошибок. Вещи запускаются к "просто работе" при переключении на этот стиль. (LINQ запрашивают синтаксис, который я не нахожу слишком полезными, если запросы не очень сложны с большим количеством промежуточных значений. В этих случаях синтаксис разберется во всех проблемах, для которых необходимо было бы иначе раздать кортежи.)
Затем, поддержка языка (в C#, и в следующей версии VB) для анонимных методов позволяет Вам писать намного больше конструкций намного более коротким способом. Например, обработка асинхронного обратного вызова может быть определена в методе, который инициирует ее. Используя закрытие здесь приведет к Вам не имеющий необходимость связать работоспособное состояние в параметр непрозрачного объекта и выбрасывающий его позже.
Способность использовать функции высшего порядка получает Вас думающий намного более в общем. Таким образом, Вы начнете видеть, куда Вы могли просто передать в лямбде и решить вещи, более опрятные и более чистые. На данном этапе Вы поймете, что вещи только действительно работают при использовании дженериков. Несомненно, это - 2,0 функции, но использование намного более распространено, когда Вы раздаете функции.
И вокруг там, Вы входите в точку убывающей доходности. Стоимость объявления и использования funcs и объявления всех универсальных параметров типа (в C# и VB) довольно высока. Компилятор не разработает его для Вас, таким образом, необходимо будет сделать все это вручную. Это добавляет огромную сумму издержек и трения, которое ограничивает, как далеко можно пойти.
Так, этот весь "LINQ"? Зависит от маркетинга, возможно. Нажатие LINQ сделало этот стиль из программирования намного легче в C#, и все LINQ основаны на идеях FP.