Топ вещей из Java, которых мне не хватает в C#



Спор "Java vs. C#" существует чуть меньше, чем вечность. Есть много статей, затрагивающих разные участки его спектра: Что есть в C# чего нет в Java, что языки друг у друга позаимствовали, у одних LINQ, у других обратная совместимость, в общем, тысячи их.

Однако, я никогда не видел, чтобы писали о чём-то, что в Java, с точки зрения фич языка есть, чего в C# нет. Впрочем, я здесь не для того, чтобы спорить. Эта статья призвана выразить моё субъективное мнение и заполнить небольшой пробел по теме, озвученной в заголовке.

Оба языка крутые, востребованные, у меня нет цели принизить один на фоне другого. Наоборот, хочу озвучить, что можно было бы, на мой взгляд, привнести, и порассуждать о том, насколько это нужно. Поэтому перейдём сразу к списку.

1. Class based Enum​

Ни для кого не секрет, что в отличие от Java, в C# и C++ перечисления это именованные числовые константы. А что есть перечисления в Java? По сути, синтаксический сахар поверх класса. Напишем какое-нибудь перечисление, например. для хранения типов "слов", распознаваемых лексическим анализатором:
C#:
Please, Log in or Register to view codes content!

И поскольку перечисление это тот же класс, то можно накрутить конструктор, методы, поля, да даже реализацию интерфейса! Добавим возможность константам перечисления трансформироваться в регулярное выражение:
C#:
Please, Log in or Register to view codes content!

А как сделать подобное в C#? Есть два варианта:
  1. Атрибуты и методы расширений с рефлексией (нельзя реализовывать интерфейсы):
C#:
Please, Log in or Register to view codes content!

  1. Классы с публичными статическими константами:
C#:
Please, Log in or Register to view codes content!

Напрашивается вопрос:
Особенно актуальный при наличии новых возможностей языка в последних версиях относительно ключевого слова switch.

2. Full support of covariant return types​

Please, Log in or Register to view URLs content!
Если раньше код писался примерно так:
C#:
Please, Log in or Register to view codes content!

То сейчас лишние конструкции можно опустить:
C#:
Please, Log in or Register to view codes content!

В Java это было почти всегда, и сама возможность работала чуть шире. Она распространялась на реализацию и расширение интерфейсов. Например, я описываю структуру, которую можно копировать вместе данными. Для этого мне нужно указать, что данные копируются. За это отвечает контракт Cloneable. По умолчанию, метод clone возвращает Object. Однако, чтобы не засорять код кастами, я могу написать, что clone возвращает то, что копируется:
C#:
Please, Log in or Register to view codes content!

В C# так сделать нельзя, выйдет ошибка:
Method 'Clone' cannot implement method from interface 'System.ICloneable'. Return type should be 'object'.
C#:
Please, Log in or Register to view codes content!

Почему у интерфейсов ещё нет ковариантности возвращаемого типа - вопрос открытый,
Please, Log in or Register to view URLs content!
.

3. Functional Interfaces​

В Java есть понятие функциональный интерфейс. Функциональный интерфейс (functional interface) – интерфейс с единственным абстрактным методом. Основная фишка таких интерфейсов в том, что их экземпляры можно инициализировать с помощью лямбда выражений (начиная с Java 8):
C#:
Please, Log in or Register to view codes content!

Однако, о том, почему именно так всё устроено, нетрудно догадаться, если посмотреть, на что предлагает заменить IDE значение, присваиваемое переменной add типа IntegerBinaryExpression:



Если нажать на предлагаемый replace, то получим:
C#:
Please, Log in or Register to view codes content!
Всё это, вместе с синтаксисом "пуговицы" (::), говорит об одном: функциональные интерфейсы - всего лишь механизм реализации callback'ов в Java. В C# есть делегаты, поэтому надобность в подобном сахаре крайне сомнительна, хоть и выглядит удобно, особенно для интерфейсов, экземпляры которых используются в проекте единожды.

4. Anonymous interface implementation​

Предыдущий пример, возможно, стоило рассмотреть именно в этой секции, поскольку он является демонстрацией частного случая крутой, на мой взгляд, фичи Java - анонимная реализация интерфейсов.

Возьмём теперь контракт, у которого не меньше двух методов:
C#:
Please, Log in or Register to view codes content!

И если начать набирать new Pair для создания экземпляра интерфейса, то нам не выскочит ошибка о том, что нельзя создавать инстансы абстрактных сущностей, а предложение реализовать методы:
C#:
Please, Log in or Register to view codes content!

Также такие штуки можно проворачивать и с классами (абстрактными и не очень):
C#:
Please, Log in or Register to view codes content!

Эта фича открывает новые возможности для создания программного обеспечения в случаях, когда надо не раздувать структуру проекта и на лету создавать новые реализации контрактов, или необходимо инкапсулировать какие-то специфичные сценарии использования контракта. Безусловно, жду в C#, все возможности у CLR для этого есть.
Please, Log in or Register to view URLs content!
.

Заключение​

Поделился с Вами о своих взглядах о возможных направлениях развития языка программирования C# и освятил, ранее не тронутую тему, о том, чего в C# нет, что в Java есть. Надеюсь, было интересно и полезно! Спасибо, что прочитали!

Автор статьи: Stefanio