Широкие возможности

Поддерживаемые особенности


FastScript .NET поддерживает следующие особенности языка C# (наиболее полно поддерживается спецификация C# 1.0, с добавлением многих особенностей более поздних версий языка):

C# 1.0:

●    Классы (Classes)
●    Структуры (Structs)
●    Перечисления (Enums)
●    Интерфейсы (Interfaces)
●    События (Events)
●    Перегрузка операторов (Operator overloading)
●    Пользовательские операторы конверсии типов (User-defined conversion operators)
●    Свойства (Properties)
●    Индексные свойства (Indexers)
●    Выходные параметры методов (Output parameters - out, ref)
●    Массив параметров (params arrays)
●    Делегаты (Delegates)
●    Операторы и выражения (Operators and expressions)
●    Буквальный идентификатор "@" (Verbatim identifier)

C# 2.0:

●    Обобщенные типы (Generics)
●    Частичные типы (Partial types)
●    Nullable типы (Nullable value types)
●    Разные модификаторы доступа у getter/setter (Getter/setter separate accessibility)
●    Статические классы (Static classes)

C# 3.0:

●    Авто-свойства (Auto-implemented properties)
●    Методы расширения (Extension methods)
●    Объявление переменных без указания типа (Implicitly typed local variables)

C# 4.0:

●    Значения параметров по умолчанию (Optional arguments)

C# 6.0:

●    Инициализаторы для авто-свойств (Auto-property initializers)
●    Свойства и методы, возвращающие выражение "=>" (Expression bodied members)
●    Оператор проверки на null "?." (Null propagator)

C# 7.0:

●    Выходные переменные (Out variables)
●    Локальные функции (Local functions)

C# 8.0:

●    Модификатор "readonly" для полей (Readonly members)
●    Статические локальные функции (Static local functions)
●    Операторы объединения null "??" и "??=" (Null-coalescing operators)

C# 9.0:

●    Инструкции верхнего уровня (Top-level statements)

 


 

Неподдерживаемые особенности


Следующие особенности C# 1.0 не поддерживаются:

●    Директивы препроцессора (Preprocessor directives - #if, #region, etc)
●    Атрибуты (Attributes)
●    Неуправляемый код (Unmanaged code: pointers, unsafe keyword, P/Invoke)
●    Инструкции checked, unchecked (checked, unchecked statements)
●    Инструкция goto (goto statement)

 


 

Ограниченная поддержка


Термины, используемые ниже: "хост" означает ваше .net приложение; "скрипт" означает нечто, определенное в коде скрипта.

 


 

Наследование классов


Классы, определенные в скрипте, можно наследовать от других скриптовых классов либо от System.Object:

class MyScriptClass: OtherScriptClass // ok
class MyScriptClass: Object // ok
class MyScriptClass // ok, same as Object
class MyScriptClass: ArrayList // error

 


 

Структуры


Структура в FastScript представляет собой обычный класс. FastScript добавляет специальные методы для копирования структуры, когда ее значение передается в метод или в другую переменную. Объявление переменной, имеющей тип структуры, не создает экземпляр структуры автоматически:

MyStruct s; // s is null
s = new MyStruct(); // and must be initialized before use

 


 

Взаимодействие с хостом


Класс, определенный в скрипте, виден хосту как экземпляр FastScript.Runtime.DataContext. 

Вы можете переопределять следующие методы в скриптовом классе:

●    ToString
●    Equals
●    GetHashCode

Переопределенные методы будут также использоваться хостом.

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

 


 

Nullable типы


Nullable типы могут использовать только типы хоста. 

 


 

Обобщенные типы и методы


В скрипте можно использовать только обобщенные типы и методы хоста. Вы не можете определять обобщенный тип или метод в скрипте.

 


 

Type forwarding


Если тип хоста обозначен как "forwarded", его нужно явно использовать в хосте, чтобы была возможность его использования в скрипте. Например:

var list = new System.ComponentModel.BindingList<int>(); // error, BindingList does not exist

Если добавить следующую строку кода в ваше приложение, скрипт будет скомпилирован без ошибок:

new System.ComponentModel.BindingList<int>();

 


 

Делегаты


Вы можете создавать делегаты на основе любых методов (определенных в скрипте или хосте). Передача делегатов хост не поддерживается. Также не поддерживается создание делегатов Action<> и Func<>.

 


 

Конверсии типов (implicit, explicit)


Конверсия типов, определенная пользователем (в коде скрипта или в хосте), ограничена теми типами, которые определены явно. Пример: если определена конверсия T->int, вы можете ее использовать. Но вы не сможете использовать конверсию T->float, если она явно не определена.

var m = new My();

int intValue = m; // ok
float floatValue = m; // error

int explicitIntValue = (int)m; // ok: explicit is not defined, but we have implicit one
float explicitFloatValue = (float)m; // error

floatValue = (int)m; // use this way

public class My
{
  private object _value;
  public static implicit operator int(My m) => (int)m._value;
}

 


 

Использование FastScript в Native AOT


В скрипте можно использовать только типы, доступные в хосте. Приложение, скомпилированное в режиме Native AOT, может не содержать некоторые типы (или члены типов), которые вы бы хотели использовать в скрипте, потому что тип/член был исключен из сборки (trimmed).

Другая проблема - использование обобщенных типов/методов. В Native AOT, вы можете использовать те обобщенные типы, которые доступны в хосте. Например, хост использует класс List<int>, но не пользуется классом List<double>. Первый можно будет использовать в скрипте, но при попытке создать тип List<double> будет выдана ошибка.

Таким образом, ваша задача будет состоять в том, чтобы сделать типы (и члены типов) статически доступными в вашем приложении, чтобы их можно было использовать в скрипте. Это можно сделать различными способами (создание экземпляров типов, использование атрибутов):

[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(List<>))]

public void EnsureAOTVisible()

{

  var list = new List<int>();

}

Если в хосте статически доступен обобщенный тип, то поддерживается его использование с параметрами, представляющими reference type. Например, если доступен тип List<>, то можно создавать типы List<object>, List<string>, List<ArrayList> и т.п.