2009-02-26 3 views
68

Я знаю, что C# получает много поддержки параллельного программирования, но AFAIK по-прежнему нет конструкций для проверки побочных эффектов, верно?Чистые функции в C#

Я предполагаю, что теперь сложнее, когда C# уже выложен. Но планируете ли вы это сделать? Или F # единственный язык .NET, который имеет конструкции для проверки побочных эффектов?

ответ

156

C# язык не есть, но .NET может быть.

по контрактам библиотека + статические средства анализа вводится в .NET 4 может ввести эти:

Microsoft использует [Неизменное] и [Pure] внутри .NET 3.5 рамки прямо сейчас.

Например, см. [Microsoft.Contracts.Immutable] и [Microsoft.Contracts.Pure] внутри .NET 3.5 в System.Core.dll. К сожалению, они внутренние. Однако Microsoft.Contracts. * В основном рождается из исследования SpeC#, а SpeC# была сложена в API контрактов, который будет частью .NET 4.0.

Мы посмотрим, что из этого получилось. Я не проверял, не содержат ли в предварительных версиях .NET 4.0 битов любые API, такие как [Pure] или [Immutable] в API контрактов. Если они это сделают, я бы предположил, что инструмент статического анализа будет тем, чтобы обеспечить соблюдение правила, а не компилятора.

Редактировать Я только что загрузил Microsoft.Contracts.dll с latest pre-release drop of MS Code Contracts на этой неделе. Хорошие новости: в библиотеке существуют атрибуты [Pure] и [Mutability (Mutability.Immutable)], которые предполагают, что они будут в .NET 4.0. Woohoo!

Редактировать 2 Теперь, когда .NET 4 был выпущен, я просмотрел эти типы. [Pure] все еще присутствует в System.Diagnostics.Contracts namespace. Он не предназначен для общего использования, а скорее для использования с проверкой до и после условия контракта API. Он не является компилятором, neither does the Code Contract checker tool enforce purity. [Mutability] ушел. Интересно, что, когда Microsoft использовала атрибуты Mutability и Pure в .NET 3.5 (во внутреннем классе BigInteger в System.Core.dll), .NET 4 переместил BigInteger в System.Numerics и лишил [Pure] и [Mutability] атрибуты этого типа. Нижняя строка: появляется .NET 4 ничего не делает для проверки побочных эффектов.

редактировать 3 С недавнего времени (в конце 2011) просмотров Microsoft Rosyln компилятором как услуга инструменты - как полагают, запланировано на RTM в Visual Studio 2015 - выглядеть они будут в состоянии поддерживать такие вещи; вы можете написать расширения компилятору, чтобы проверить чистоту и неизменность, а также выдавать предупреждения компилятора, если что-то, украшенное этими атрибутами, не соответствует правилам. Несмотря на это, мы смотрим на несколько лет, чтобы поддержать это.

Редактировать 4 Теперь, когда Rosyln существует с лета 2015 года, способность создавать расширение компилятора для чистой/неизменяемости действительно существует. Тем не менее, это ничего не делает для существующего кода рамки, а также для стороннего библиотечного кода. Но на горизонте находится C# 7 proposal for immutable types. Это будет принудительно применено компилятором и введет новое ключевое слово неизменным в C# и атрибут [Неизменяемый] в платформе .NET. Использование:

// Edit #4: This is a proposed design for C# 7 immutable as of June 2015. 
// Compiler will implicitly mark all fields as readonly. 
// Compiler will enforce all fields must be immutable types. 
public immutable class Person 
{ 
    public Person(string firstName, string lastName, DateTimeOffset birthDay) 
    { 
     FirstName = firstName; // Properties can be assigned only in the constructor. 
     LastName = lastName; 
     BirthDay = birthDay; 
    } 

    public string FirstName { get; } // String is [Immutable], so OK to have as a readonly property 
    public string LastName { get; } 
    public DateTime BirthDay { get; } // Date is [Immutable] too. 
} 

редактировать 5 Это ноября 2016, и, кажется, неизменные типы были исключены из C# 7. Там всегда есть надежда на C# 8. :-)

редактировать 6 Это ноября 2017. C# 8 выходит на первый план, и пока у нас не будет чистых функций, у нас будет readonly structs. Это делает структуру неизменной, что позволяет несколько оптимизаций компилятора.

+1

Другое примечание: начиная с этой недели, [Pure] является общедоступным, но [Mutability (...)] является внутренним. Посмотрим, изменится ли это. –

+0

Следует также отметить, являются ли эти атрибуты для общего использования или предназначены только для использования в API контрактов. Я надеюсь, что они, как правило, полезны для использования на всей кодовой базе, независимо от того, используется ли в ней фактический System.Diagnostics.Contract API. –

+65

+1 для обновления ответа на древний вопрос, когда мир изменился. – Emile

17

Для проверки побочных эффектов нет ничего, кроме того, чтобы убедиться, что тип неизменен, что является меньшим шагом по тому же маршруту IMO.

Я не верю, что в C# 4.0 что-то идет по трубе (хотя я мог легко ошибаться). Я действительно надежда, что неизменность оказывает влияние на C# 5.0; конечно же, Эрик Липперт довольно много писал об этом, и люди в MS думали о параллелизме.

Извините, но это не более обнадеживающая картина.

Редактировать: Judah's answer значительно ярче ... будет ли поддержка фрейма достаточной для вас? :) (я не был бы полностью удивлен, если некоторые аспекты кодовых контрактов были не готовы к .NET 4.0, заметьте - если бы они сохранили начальный выпуск относительно небольшой и увеличили его позже.)

+0

Спасибо Jon. Ваше понимание всегда приветствуется :) Я просто хотел посмотреть, что происходит в этом отделе. –

+1

Взгляды приветствуются, будет ли этот ответ еще полезен или его следует удалить в свете Иудеи. С удовольствием удаляем его, если это необходимо. –

+0

Мне бы очень хотелось, чтобы Runtime гарантировало чистоту и неизменность, точно так же, как и для безопасности типов. Таким образом, вы можете создать чистый язык поверх CLR и безопасно вызывать (или быть вызванным) C#. –

14

В принципе, проверяется, является ли что-то неизменным & ли код не имеет побочных эффектов. Все поля структуры класса/данных должны быть только для чтения, а их тип должен быть другим неизменяемым объектом. Нам также нужен способ отметить делегат как «чистый» (свободный от побочных эффектов), но это, вероятно, будет возможно.

Однако проблема заключается в том, что это часто слишком ограничительно. В F # вы обычно пишете код в побочном эффекте & неизменяемым стилем, но часто полезно использовать некоторую мутацию локально. Это не нарушает общую чистоту (в некотором смысле) и упрощает запись кода. Тем не менее, проверка этого автоматически затруднена (в том смысле, что это интересная теоретическая проблема.)

Например, отлично работать с массивами «чистым» способом. У вас могут быть такие методы, как Array.map, которые применяют некоторую функцию ко всем элементам и возвращают массив без изменения исходного. Эта функция мутирует (вновь созданный) массив перед ее возвратом, но массив не мутирует нигде, так что это принципиально чистый, но трудно проверить (и это довольно полезный шаблон программирования в F #).

Итак, я думаю, что многое можно сделать, но просто запретить все побочные эффекты не так хорошо, как кажется. Хорошая вещь о контрактах заключается в том, что они могут быть, вероятно, использованы и в этом сценарии.

Смежные вопросы