Документация → Встроенные функции
WriteLine("Hello, world!");
Write и WriteLine могут использовать заданные сведения о форматировании.
string name="John";
string surname="Doe";
WriteLine("Logged in as {0} {1}", name, surname); //Logged in as John Doe
WriteLine("Current date and time in RFC1123 format: {0:R}", Now()); // Current date and time in RFC1123 format: Fri, 19 Feb 2021 11:07:27 GMT
string ReadLine() 2 - Считывает следующую строку символов из стандартного входного потока. Можно задать текст, который будет выводиться перед вводом. Использует Console.ReadLine.object key=ReadKey("Нажмите Enter");
WriteLine();
// Нажимаем клавишу ввод
if(key==object\"Enter") WriteLine("Вы нажали Enter (references are equal)."); // не сработает, т.к. сравниваются ссылки, а не значения.
if(ToString(key)=="Enter") WriteLine("Вы нажали Enter."); //сработает. ToString(key) вернёт имя клавиши.
key=ReadKey("Нажмите s");
WriteLine();
// Нажимаем клавишу s (любая раскладка)
if(ToString(key)=="S") WriteLine("Вы нажали S."); // сработает, и неважно, маленькую или большую 's' вы ввели, - имя клавиши будет 'S'.
key=ReadKey("Нажмите ф");
WriteLine();
// Нажимаем 'ф' (русская раскладка)
WriteLine(key+"; "+ToInt(key)); // A; 65 // A - это имя клавиши, а не символ. 65 - её код. На русско-английской клавиатуре 'ф' и 'a' (англ.) находятся на одной клавише.
if(ToInt(key)==1092) WriteLine("key==1092"); // не сработает, 1092 - код символа 'ф', но key сконвертится в 65 (код клавиши A).
if(ToInt(key)==65) WriteLine("key==65"); // сработает потому, что key при конвертировании в int будет 65.
if(ToChar(key)=='ф') WriteLine("key=='ф'"); // сработает потому, что key сконвертится в символ 'ф', и будут сравниваться char-ы.
if(ToString(key)=="ф") WriteLine("key==\"ф\""); // не сработает, т.к. ToString(key) вернёт 'A'.
object KeyModifiers(object key) - Возвращает побитовое сочетание значений из перечисления ConsoleModifiers, указывающее, были ли одновременно с клавишей консоли нажаты управляющие клавиши SHIFT, ALT или CTRL. Функция принимает объект типа PressedKey, возвращаемый ReadKey(). Использует ConsoleKeyInfo.Modifiers.
object key=ReadKey(true);
// Нажимаем любую клавишу вместе с Alt и Shift
object km=KeyModifiers(key);
WriteLine(GetType(km)); // System.ConsoleModifiers
if(ToString(km)=="Alt, Shift") WriteLine("Нажаты Alt и Shift"); // сработает
if(ToInt(km)==3) WriteLine("km==3"); // сработает, 3 это ConsoleModifiers.Alt (1) + ConsoleModifiers.Shift (2)
int CursorLeft() - Возвращает позицию столбца курсора в буферной области. Использует Console.CursorLeft.WriteLine(Substring("hello", 1, 2)); // возвращает "el"
WriteLine(Substring("hello", 3)); // возвращает "lo"
string Slice(string text, int startIndex, int stopIndex) 4 - возвращает часть строки, но в отличие от Substring нужно задавать, с какого по какой символ (индекс) брать часть (символ по последнему индексу не будет включён). Можно указывать отрицательные индексы (например, -2 это длина строки минус 2). Возвращает пустую строку, если индексы выходят за пределы. Есть перегрузка для работы с массивами. Использует String.Substring.WriteLine(Slice("abcde", 2)); //cde
WriteLine(Slice("abcde", 2, 4)); //cd
WriteLine(Slice("abcde",, 3)); //abc //можно писать Slice("abcde", 0, 3), но перегрузка без 0 работает чуть быстрее
WriteLine(Slice("abcde", 3,)); //de
WriteLine(Slice("abcde", -2)); //de
WriteLine(Slice("abcde", -4, -2)); //bc
WriteLine(Slice("abcde", -10, 20)); //abcde
string Left(string text, int length) - Возвращает строку, содержащую указанное число знаков с левой стороны строки. Число знаков может быть больше длины строки. Использует String.Substring.str = Left("hello", 2); // возвращает "he"
string Right(string text, int length) - Возвращает строку, содержащую указанное число знаков с правой стороны строки. Число знаков может быть больше длины строки. Использует String.Substring.str = Right("hello", 3); // возвращает "llo"
int Length(string text) - Возвращает число знаков в строке. Использует String.Length. Есть перегрузка для возврата размера массива.l = Length("hello"); // возвращает 5
int IndexOf(string text, string value, int startIndex) 12 - Возвращает индекс с отсчетом от нуля первого вхождения указанной подстроки. Возвращает -1, если строка не найдена. Использует String.IndexOf. По умолчанию comparisonType равно StringComparison.CurrentCulture. У метода есть перегрузка для поиска элемента в массиве.i = IndexOf("hello", 'l'); // возвращает 2
i = IndexOf("hello", "ell"); // возвращает 1
i = IndexOf("hello", 'l', 0); // возвращает 2
i = IndexOf("hello", 'l', 3); // возвращает 3
i = IndexOf("hello", "ell", 0); // возвращает 1
i = IndexOf("hello", "Ell", ToEnum("OrdinalIgnoreCase", "System.StringComparison")); // возвращает 1
i = IndexOf("hello", "Ell", true); // возвращает 1
i = IndexOf("hello", "Ell", 0, true); // возвращает 1
i = IndexOf("hello", 'e', 0, 5); // возвращает 1
i = IndexOf("hello", 'l', 0, 2); // возвращает -1
i = IndexOf("hello", 'l', 3, 2); // возвращает 3
i = IndexOf("hello", "el", 0, 5); // возвращает 1
i = IndexOf("hello", "el", 0, 2); // возвращает -1
i = IndexOf("hello", "el", 1, 2); // возвращает 1
i = IndexOf("hello", "el", 0, 5, 1); // возвращает 1
i = IndexOf("hello", "el", 0, 5, ToEnum("OrdinalIgnoreCase", "System.StringComparison")); // возвращает 1
i = IndexOf("hello", "el", 0, 5, true); // возвращает 1
int LastIndexOf(string text, string value, int startIndex) 12 - Работает также как IndexOf, только возвращает позицию индекса последнего вхождения указанной строки или символа. Использует String.LastIndexOf. У метода есть перегрузка для поиска элемента в массиве.i = LastIndexOf("hello", 'l'); // возвращает 3
i = LastIndexOf("HELLO", "el", true); // возвращает 1
i = LastIndexOf("hello", 'l', 2); // возвращает 2
i = LastIndexOf("hello", "l", 3); // возвращает 3
int IndexOfAny(string text, char[] anyOf, int startIndex, int count) 3 - Возвращает индекс первого обнаруженного в строке символа из указанного char-массива. Использует String.IndexOfAny. char[] chars=new char[]{'d', 'c', 'e'};
i=IndexOfAny("abcde", chars); //2
i=IndexOfAny("abcde", chars, 3); //3
i=IndexOfAny("abcde", chars, 2, 3); //2
int LastIndexOfAny(string text, char[] value, int startIndex, int count) 3 - Работает также как IndexOfAny, только возвращает позицию индекса последнего вхождения любого из символов. Использует String.LastIndexOfAny. char[] chars=new char[]{'b', 'c', 'd'};
i=LastIndexOfAny("abcde", chars); //3
i=LastIndexOfAny("abcde", chars, 2); //2
i=LastIndexOfAny("abcde", chars, 2, 3); //2
string Trim(string text, char trimChar) 2 - Возвращает новую строку, в которой удалены все начальные и конечные вхождения заданного символа. Если trimChar не указывать, то удаляться будут начальные и конечные символы пробела. Использует String.Trim.str=Trim(" hello "); // возвращает "hello"
str=Trim("__hello_",'_'); // возвращает "hello"
string TrimStart(string text, char trimChar) 2 - Удаляет все начальные вхождения указанного символа. Использует String.TrimStart.WriteLine(TrimStart(" hello ")+";"); //hello ;
WriteLine(TrimStart("__hello_", '_')+";"); //hello_;
string TrimEnd(string text, char trimChar) 2 - Удаляет все конечные вхождения символа из текущей строки. Использует String.TrimEnd.WriteLine("_"+TrimEnd(" hello ")); //_ hello
WriteLine(TrimEnd("__hello_", '_')); //__hello
string ToUpper(string text) - Возвращает копию строки, переведенную в верхний регистр. Использует String.ToUpper.str=ToUpper("hello"); // возвращает "HELLO"
string ToLower(string text) - Возвращает копию строки, переведенную в нижний регистр. Использует String.ToLower.str=ToLower("HELLO"); // возвращает "hello"
string ToUpperFirst(string text) - Преобразует первый символ строки в верхний регистр. Использует String.ToUpper.str=ToUpperFirst("hello"); // возвращает "Hello"
string ToLowerFirst(string text) - Преобразует первый символ строки в нижний регистр. Использует String.ToLower.str=ToLowerFirst("HELLO"); // возвращает "hELLO"
string Replace(string text, string oldValue, string newValue, int comparisonType) 5 - Возвращает новую строку, в которой все вхождения заданной строки в текущем экземпляре заменены другой заданной строкой с использованием указанного типа сравнения. По умолчанию comparisonType равно 4 (StringComparison.Ordinal). Чтобы замена велась без учёта регистра, нужно задать comparisonType равным 5 (StringComparison.OrdinalIgnoreCase). Есть перегрузки принимающие enum StringComparison или bool, задающее ignoreCase. Использует String.Replace.str = Replace("hello", "ell", "ABC"); // возвращает "hABCo"
str = Replace("HELLO", "ll", "xx", 5); // возвращает "HExxO"
object ordinalIgnoreCase=ToEnum("OrdinalIgnoreCase", "System.StringComparison"); // создаём enum
str = Replace("HELLO", "ll", "xx", ordinalIgnoreCase); // возвращает "HExxO"
str = Replace("Hello", 'l', 'x'); // возвращает "Hexxo"
str = Replace("HELLO", "ll", "xx", true); // возвращает "HExxO"
string Remove(string text, int startIndex, int count) 2 - Возвращает новую строку, в которой было удалено указанное число символов в указанной позиции. Использует String.Remove.str = Remove("hello", 2, 2); // возвращает "heo"
str = Remove("hello", 2); // возвращает "he"
string Insert(string text, int startIndex, string value) 2 - Возвращает новую строку, в которой указанная строка вставляется в указанной позиции индекса. Использует String.Insert.str = Insert("hello", 2, "ABC"); // возвращает "heABCllo"
string PadLeft(string text, int totalWidth, char paddingChar) 2 - Возвращает новую строку, в которой знаки строки выровнены по правому краю путем добавления слева пробелов или указанного символа до указанной общей длины. Использует String.PadLeft.WriteLine(PadLeft("hello", 7)); // возвращает " hello"
WriteLine(PadLeft("hello", 7, '*')); // возвращает "**hello"
string PadRight(string text, int totalWidth, char paddingChar) 2 - Возвращает новую строку, в которой знаки строки выровнены по левому краю путем добавления справа пробелов (или указанного символа) до указанной общей длины. Использует String.PadRight.WriteLine(PadRight("hello", 7)); // возвращает "hello "
WriteLine(PadRight("hello", 7, '*')); // возвращает "hello**"
bool StartsWith(string text, string value, int comparisonType) 6 - Определяет, совпадает ли начало этого экземпляра строки с заданной строкой при сравнении с учетом заданного параметра сравнения (по умолчанию StringComparison.CurrentCulture). Использует String.StartsWith.b = StartsWith("hello", 'h'); // возвращает true
b = StartsWith("hello", "he"); // true
b = StartsWith("Hello", "he", 5); // true
b = StartsWith("Hello", "he", ToEnum("OrdinalIgnoreCase", "System.StringComparison")); // true
b = StartsWith("Hello", "he", true); // true
b = StartsWith("Hello", "he", true, Create("System.Globalization.CultureInfo", "es-ES", false)); // true
bool EndsWith(string text, string value, int comparisonType) 6 - Определяет, совпадает ли конец экземпляра строки с заданной строкой при сравнении с учетом заданного параметра сравнения. Использует String.EndsWith.b = EndsWith("hello", 'o'); // возвращает true
b = EndsWith("hello", "lo"); // true
b = EndsWith("HELLO", "lo", 5); // true
b = EndsWith("HELLO", "lo", ToEnum("OrdinalIgnoreCase", "System.StringComparison")); // true
b = EndsWith("HELLO", "lo", true); // true
b = EndsWith("HELLO", "lo", true, Create("System.Globalization.CultureInfo", "es-ES", false)); // true
string Format(string text, string format, params object[] args) 2 - Преобразует значения объектов в строки на основе указанных форматов и вставляет их в другую строку. Использует String.Format.string product="blazer";
decimal price = 15.99m;
string s = Format("The current price of the {0} is {1:C2}.", product, price); //возвращает (en-US): The current price of the blazer is $15,99.
bool IsNumeric(string value) - Определяет, является ли строка числом. Использует Decimal.TryParse.b=IsNumeric("123.4567"); // False
b=IsNumeric("123,4567"); // True
b=IsNumeric("123,45,67"); // False
WriteLine(Ord('b')); // возвращает 98
WriteLine(Ord('Б')); // возвращает 1041
WriteLine(Ord("Hello",1)); // возвращает 101 // код символа 'e'
int Asc(char c, string encoding) 8 - возвращает ASCII-код символа в таблице кодов указанной кодировки (по умолчанию Latin1). Только для однобайтовых кодировок!WriteLine(Asc('b')); // 98
WriteLine(Asc('Б')); // 63 // 63 - это символ '?' в Latin1. Это значит, что укзанный символ не найден.
WriteLine(Asc('Б', "windows-1251")); // 193
WriteLine(Asc('Б', "utf-8")); // 208 // т.к. в utf-8 символ представлен двумя байтами, то 208 - это только первый байт (второй 145).
WriteLine(Asc('Щ')); // 63 // нет такого символа в Latin1.
WriteLine(Asc('Б', "windows-1250")); // 63 // нет такого символа в Windows-1250.
WriteLine(Asc("Тест", 2, "windows-1251")); // возвращает 241 // код символа 'c'
WriteLine(Chr(Asc("Б", "windows-1251"), "windows-1251")); // Б // Asc и Chr - обратные функции.
object enc=typeof("System.Text.Encoding")->GetEncoding("windows-1251");
WriteLine(Asc('Б', enc));
char Chr(int code, string encoding) 3 - возвращает символ по коду в таблице указанной кодировки (по умолчанию Latin1).WriteLine(Chr(193, "windows-1251")); // Б
WriteLine(Chr(193)); // A //символ в Latin1
WriteLine(Chr(119)); //w
object enc=typeof("System.Text.Encoding")->GetEncoding("windows-1251");
WriteLine(Chr(193, enc));
for(int i=0;i<256;i++) WriteLine(i+") "+Chr(i)); //Вывод всех символов из Latin1
char CharAt(string text, int pos) - возвращает символ, расположенный по указанному индексу. Индексы начинаются с нуля. Если нужно взять от конца, указав отрицательный индекс, то используйте функцию At(строка, позиция), у которой есть перегрузка для возврата символа строки.WriteLine(CharAt("abc",1)); //b
WriteLine("abc"[1]); //b //"abc"[1] интерпретатор преобразовывает в CharAt("abc",1)
bool IsControl(char c) - управляющим символом. bool IsDigit(char c) - десятичной цифрой. bool IsHighSurrogate(char c) - старшим символом-заместителем. bool IsLetter(char c) - буквой. bool IsLetterOrDigit(char c) - буквой или десятичной цифрой. bool IsLower(char c) - буквой нижнего регистра. bool IsLowSurrogate(char c) - младшим символом-заместителем. bool IsNumber(char c) - цифрой. |
bool IsPunctuation(char c) - знаком препинания. bool IsSeparator(char c) - знаком-разделителем. bool IsSurrogate(char c) - имеет ли символ заменяющую кодовую единицу. bool IsSurrogatePair(char c1, char c2) - образуют ли два заданных char-а суррогатную пару. bool IsSymbol(char c) - символьным знаком. bool IsUpper(char c) - буквой верхнего регистра. bool IsWhiteSpace(char c) - пробелом. |
bool ToBool(object value) - в Boolean (логическое значение: true или false). byte ToByte(object value) - в Byte (8-битовое целое число без знака). short ToShort(object value) - в Int16 (16-разрядное целое число со знаком). int ToInt(object value) - в Int32 (32-разрядное целое число со знаком). long ToLong(object value) - в Int64 (64-разрядное целое число со знаком). float ToFloat(object value) - в Single (число одиночной точности с плавающей запятой). double ToDouble(object value) - в Double (число двойной точности с плавающей запятой). decimal ToDecimal(object value) - в Decimal (десятичное число с плавающей запятой). |
date ToDate(object value) - в DateTime (время, обычно выраженное как дата и время суток). string ToString(object value) - в строку. string ToString(byte|short|int|long value, int toBase) - в эквивалентное строковое представление в указанной системе счисления (2, 8, 10 или 16). object ToChar(object code) - в символ (тип char). object ToEnum(string|object value, string|object type) - в Enum (преобразует значение заданного целого числа, либо строки, в член перечисления). В type можно указывать строку с именем типа, либо передавать объект Type. |
object protocol=ToEnum(3072, "System.Security.Authentication.SslProtocols, System"); // SslProtocols.Tls12.
WriteLine(protocol); //Tls12
object comparison=ToEnum("InvariantCulture", "System.StringComparison"); // StringComparison.InvariantCulture
WriteLine(comparison); //InvariantCulture
object enumType=typeof("System.StringSplitOptions");
object splitOptions=ToEnum("RemoveEmptyEntries", enumType); // StringSplitOptions.RemoveEmptyEntries
WriteLine(splitOptions); //RemoveEmptyEntries
Конвертирование в разные системы счисления:str=ToString(123, 2); // возвращает "1111011"
str=ToString(123, 8); // возвращает "173"
str=ToString(123, 10); // возвращает "123"
str=ToString(123, 16); // возвращает "7b"
В Char:
char c=ToChar(98); // возвращает 'b'
c=ToChar(1041); // возвращает 'Б'
c=ToChar("Т"); // возвращает 'Т'
WriteLine(Floor(4.789)); // 4
WriteLine(Ceiling(4.789)); // 5
WriteLine(Round(4.789,1)); // 4,8
WriteLine(Round(4.789, 2, ToEnum("AwayFromZero", "System.MidpointRounding"))); // 4,79
decimal Truncate(decimal d) 2 - Вычисляет целую часть заданного числа двойной точности с плавающей запятой. Для положительных чисел работает Floor, а для отрицательных - как Ceiling. Использует Math.Truncate.WriteLine(Truncate(4.9)+" / "+Floor(4.9)+" / "+Ceiling(4.9)); //4 / 4 / 5
WriteLine(Truncate(-4.9)+" / "+Floor(-4.9)+" / "+Ceiling(-4.9)); //-4 / -5 / -4
WriteLine(Pow(2, 3)); //8
decimal Abs(decimal value) 6 - Возвращает абсолютное значение (модуль) заданного числа. Использует Math.Abs.d=Abs(-5); // 5
double Sin(double d) - Возвращает синус указанного угла. Использует Math.Sin.double x = 1.0, y = 2.0;
double angle, radians, result;
const double PI = typeof("System.Math")->PI;
// Calculate the tangent of 30 degrees.
angle = 30;
radians = angle * (PI/180);
result = Tan(radians);
WriteLine("The tangent of 30 degrees is {0}.", result);
// Calculate the arctangent of the previous tangent.
radians = Atan(result);
angle = radians * (180/PI);
WriteLine("The previous tangent is equivalent to {0} degrees.", angle);
// Calculate the arctangent of an angle.
radians = Atan2(y, x);
angle = radians * (180/PI);
WriteLine();
WriteLine("The arctangent of the angle formed by the x-axis and ");
WriteLine("a vector to point ({0},{1}) is {2}, ", x, y, radians);
WriteLine("which is equivalent to {0} degrees.", angle);
/*
This example produces the following results:
The tangent of 30 degrees is 0,5773502691896257.
The previous tangent is equivalent to 29,999999999999996 degrees.
The arctangent of the angle formed by the x-axis and
a vector to point (1,2) is 1,1071487177940904,
which is equivalent to 63,43494882292201 degrees.
*/
int[] arr=new int[]{1, 2, 3, 4, 5};
WriteLine(Join("; ",arr)); // 1; 2; 3; 4; 5
WriteLine(Join('|',arr)); // 1|2|3|4|5
//Вместо массива можно передавать любой объект, тип которого реализует System.Collections.IEnumerable
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections"); //создаём List<string>
list->AddRange(new string[]{"Hello", "World", "Test"});
WriteLine(Join(", ", list)); //Hello, World, Test
string[] Split(string text, string separator, int count, int options) 10 - Возвращает строковый массив, содержащий подстроки данного экземпляра, разделенные элементами заданной строки. options - StringSplitOptions, по умолчанию 0. Использует String.Split.
string[] arr= Split("1|2|3|4|5", '|');
WriteLine(Join("; ",arr)); // 1; 2; 3; 4; 5
void Resize(some[] arr, int size) 2 - Изменяет количество элементов в одномерном массиве до указанной величины. Использует Array.Resizeint[] arr=new int[3];
WriteLine(Length(arr)); // 3
Resize(arr, 5);
WriteLine(Length(arr)); // 5
//Можно получать кол-во элементов в любых объектах
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections"); //создаём List<string>
list->AddRange(new string[]{"Hello", "World", "Test"});
WriteLine(Length(list)); // 3
int IndexOf(some[] arr, some value, int startIndex, int count) 3 - Возвращает индекс первого вхождения значения в одномерном массиве или его части. Если значение не найдено, то возвращает -1. Использует Array.IndexOf. int[] arr=new int[]{100, 234, 567, 234};
index=IndexOf(arr, 234); // 1
index=IndexOf(arr, 234, 2); // 3
index=LastIndexOf(arr, 234); // 3
index=LastIndexOf(arr, 234, 2); // 1
void Reverse(object arr, int index, int length) 2 - Изменяет порядок элементов в одномерном массиве или в его части. Использует Array.Reverse. short[] arr=new short[]{10, 20, 30, 40, 50};
Reverse(arr);
WriteLine(Join(' ', arr)); //50 40 30 20 10
void Sort(object arr) 3 - Сортирует элементы во всем одномерном массиве. Использует Array.Sort.
int[] arr=new int[]{3, 5, 1, 4, 2};
Sort(arr);
WriteLine(Join("; ", arr)); // 1; 2; 3; 4; 5
Сортировка пары одномерных массивов (один содержит ключи, а другой — соответствующие элементы) по ключам в первом массиве:
int[] keys=new int[]{5, 4, 3, 2, 1};
string[] items=new string[]{"item-1", "item-2", "item-3", "item-4", "item-5"};
Sort(keys, items);
WriteLine(Join("; ", items)); // item-5; item-4; item-3; item-2; item-1
void Copy(object sourceArray, object destinationArray, int length) 2 - Копирует диапазон элементов из массива, начиная с первого элемента, и вставляет его в другой массив, также начиная с первого элемента. Использует Array.Copy(Array, Array, Int64).
int[] arr=new int[]{1, 2, 3, 4, 5};
int c=Length(arr);
int[] arr2=new int[c];
Copy(arr, arr2, c);
WriteLine(Join("; ", arr2)); // 1; 2; 3; 4; 5
//Перегрузка: Копирует диапазон элементов из массива, начиная с заданного индекса источника, и вставляет его в другой массив, начиная с заданного индекса назначения.
c-=2;
int[] arr3=new int[c];
Copy(arr, 1, arr3, 0, c);
WriteLine(Join("; ", arr3)); // 2; 3; 4
object Array(string arrayType, object item0, object item1, ...) 4 - Создаёт массив указанного типа. Использует Array.CreateInstance.
long[] arr:=Array(long, 100L, 200L, 300L);
WriteLine(Join(", ", arr)); //100, 200, 300
char[] arr2:=Array("System.Char", 'a', 'b', 'c');
WriteLine(Join(", ", arr2)); //a, b, c
date[] arr3:=Array(date, "18.09.2021", "19.09.2021 10:15:55", "20.09.2021"); //значения string будут конвертированы в date автоматически
WriteLine(Join("; ", arr3)); //18.09.2021 0:00:00; 19.09.2021 10:15:55; 20.09.2021 0:00:00
some[] Slice(some[] arr, int startIndex, int stopIndex) 4 - возвращает новый массив, содержащий копию части исходного массива. Указывается с какого по какой элемент (индекс) брать часть (элемент по последнему индексу не будет включён). Можно указывать отрицательные индексы (например, -2 это длина массива минус 2). Возвращает пустой массив, если индексы выходят за пределы. Есть перегрузка для работы со строками. Использует Array.Copy, Enumerable.Take, Enumerable.Skip.byte[] arr=new byte[]{10, 20, 30, 40, 50, 60, 70};
byte[] newArr=Slice(arr, 2, -2); //а можно написать arr[2, -2], что интерпретатор преобразует в Slice(arr, 2, -2)
WriteLine(Join(' ', newArr)); //30 40 50
newArr=Slice(arr, 2);
WriteLine(Join(' ', newArr)); //30 40 50 60 70
newArr=Slice(arr, , 2);
WriteLine(Join(' ', newArr)); //10 20
some[] Splice(some[] arr, int startIndex, int deleteCount, some item0, some item1 ...) - изменяет содержимое массива, удаляя существующие элементы и/или добавляя новые. Использует Array.Copy.byte[] arr=new byte[]{10, 20, 30, 40, 50, 60, 70};
byte[] arr2=Splice(arr, 2, 3, 33, 44, 55); //замена элементов 2, 3, 4 (30 на 33, 40 на 44, 50 на 55)
WriteLine(Join(' ', arr)); //10 20 33 44 55 60 70
WriteLine(Join(' ', arr2)); //30 40 50
//*****
arr=new byte[]{10, 20, 30, 40, 50, 60, 70};
arr2=Splice(arr, 2, 3); //удаление трёх элементов начиная с индекса 2
WriteLine(Join(' ', arr)); //10 20 60 70
WriteLine(Join(' ', arr2)); //30 40 50
//*****
arr=new byte[]{10, 20, 30, 40, 50, 60, 70};
arr2=Splice(arr, 2, 0, 22, 222); //вставить 22 и 222 без удаления других
WriteLine(Join(' ', arr)); //10 20 22 222 30 40 50 60 70
WriteLine(Join(' ', arr2)); //ничего, т.к. массив пуст
int Insert(some[] arr, int startIndex, some item0, some item1 ...) 2 - вставляет элементы в массив и возвращает новый размер массива. Поддерживает вставку в списки (System.Collections.IList), стек (System.Collections.Stack), очередь (System.Collections.Queue).byte[] arr=new byte[]{10, 20, 30, 40, 50};
Insert(arr, 2, byte\22, byte\222);
WriteLine(Join(' ', arr)); //10 20 22 222 30 40 50
int InsertRange(some[] arr, int startIndex, object values, bool convert) 4 - вставляет элементы одного массива в другой и возвращает новый размер массива. Возможна вставка с конвертированием. Поддерживает вставку в списки, стек, очередь.int[] arr={10, 20, 30};
int[] arr2={100, 200, 300};
int c=InsertRange(arr, 1, arr2);
WriteLine(c); //6
WriteLine(Join(' ', arr)); //10 100 200 300 20 30
short[] arr3={123, 456, 789};
InsertRange(arr, 1, arr3);
WriteLine(Join(' ', arr));
long[] arr4={1111, 2222, 3333};
InsertRange(arr, 1, arr4, true); //true указывает, что нужно сконвертировать вставляемые значения в нужный тип
WriteLine(Join(' ', arr)); //10 1111 2222 3333 123 456 789 100 200 300 20 30
int ConvInsert(some[] arr, int startIndex, some item0, some item1 ...) 2 - вставляет элементы в массив с конвертированием. Поддерживает вставку в списки.byte[] arr=new byte[]{10, 20, 30, 40, 50};
ConvInsert(arr, 2, 22, 222);
WriteLine(Join(' ', arr)); //10 20 22 222 30 40 50
int Remove(some[] arr, int startIndex, int deleteCount) 4 - удаляет из массива указанное кол-во элементов начиная с индекса startIndex.byte[] arr=new byte[]{10, 20, 30, 40, 50};
RemoveRange(arr, 1, 2);
WriteLine(Join(' ', arr)); //10 40 50
int RemoveAt(some[] arr, int index) 2 - удаляет из массива или списка (System.Collections.IList) элемент по указанному индексу.int[] arr={10, 20, 30};
WriteLine(RemoveAt(arr, 1)); //2
WriteLine(Join(' ', arr)); //10 30
int RemoveAll(some[] arr, int index) 2 - удаляет из массива или списка (System.Collections.IList) все элементы, для которых выполняется условие condition. Возвращает кол-во удалённых элементов.Foo[] arr={new Foo(10), new Foo(20), new Foo(30), new Foo(40)};
WriteLine(RemoveAll(arr, Foo f, f.X>10 && f.X<40)); //2
WriteLine(Join(' ', arr)); //10 40
ReadKey();
class Foo{
public int X;
New(int x){X=x;}
string ToString(){return ToString(X);}
}
some Find(some[] arr, some var, bool condition) 2 - возвращает значение первого найденного в массиве элемента, которое удовлетворяет условию переданному в condition. В противном случае возвращается значение по умолчанию (0 для числовых и null для ссылочных).byte[] arr=new byte[]{10, 20, 30, 40, 50, 60, 70};
WriteLine(Find(arr, byte v, v>44)); //50
WriteLine(Find(arr, byte $v, v>99)); //0
//-----
Point[] points=new Point[]{new Point(2, 3), new Point(4, 5), new Point(5, 7)};
Point point=Find(points, Point p, p.X>=5 && p.Y>=5);
WriteLine(point.X+"; "+point.Y); //5; 7
point=Find(points, p, p.X==2 && p.Y>=5);
WriteLine(point==null); //True
class Point{
public int X, Y;
New(int x, int y){
X=x;
Y=y;
}
}
int FindIndex(some[] arr, some var, bool condition) 2 - возвращает индекс первого найденного в массиве элемента, который удовлетворяет условию переданному в condition. В противном случае возвращается -1.byte[] arr=new byte[]{10, 20, 30, 40, 50, 60, 70};
WriteLine(FindIndex(arr, byte v, v>44)); //4
WriteLine(FindIndex(arr, v, v>99)); //-1
//-----
Point[] points=new Point[]{new Point(2, 3), new Point(4, 5), new Point(5, 7)};
int index=FindIndex(points, Point p, p.X>=5 && p.Y>=5);
WriteLine(index); //2
index=FindIndex(points, p, p.X==2 && p.Y>=5);
WriteLine(index); //-1
class Point{
public int X, Y;
New(int x, int y){
X=x;
Y=y;
}
}
int FindAll(some[] arr, some var, bool condition) - возвращает массив элементов, которые удовлетворяет условию переданному в condition. Если элементов не найдено, то возвращается пустой массив.Foo[] arr={new Foo(3), new Foo(4), new Foo(5), new Foo(6), new Foo(7)};
Foo[] arr2=FindAll(arr, Foo f, f.X>=4 && f.X<=5);
WriteLine(Join(' ', arr2)); //4 5
ReadKey();
class Foo{
public int X;
New(int x){X=x;}
string ToString(){return ToString(X);}
}
some[] Select(some[] array, some var, some result, bool condition) 2 - Выбирает из массива или любой перечислимой коллекции элементы соответствующие условию, если таковое задано (либо все, если без условия). Может использоваться для конвертирования значений массива.
//Выбрать все числа больше 10:
int[] arr=new int[]{10, 20, 30};
int[] arr2=Select(arr, int v, v, v>10);
foreach(int x in arr2) Write(x+" "); //20 30
//Конвертирование int-массива в short[]:
int[] arr=new int[]{10, 20, 30};
short[] arr2=Select(arr, int v, ToShort(v));
foreach(short x in arr2) Write(x+" "); //10 20 30
//Выбрать все числа меньше 30 в string-массив с добавлением текста:
int[] arr=new int[]{10, 20, 30};
string[] arr2=Select(arr, int v, "Item-"+v, v<30);
foreach(string x in arr2) Write(x+" "); //Item-10 Item-20
//Выборка из List-а:
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections");
list->AddRange(new string[]{"Hello", "World", "Test"});
int n;
string[] arr2=Select(list, string str, (n++)+") "+str);
WriteLine(Join('\n', arr2));
//0) Hello
//1) World
//2) Test
//*****Далее пример выборки объектов пользовательского типа*****
//Выбираем авто фирмы Ford:
Car[] arr=new Car[]{new Car("Ford", "Mondeo"), new Car("Kia", "Rio"), new Car("Ford", "Fiesta"), new Car("Kia", "Sorento")};
Car[] arr2=Select(arr, Car car, car, car.Company=="Ford");
foreach(Car $car in arr2) WriteLine(car.Model);
//Mondeo
//Fiesta
//А теперь выбрать авто (фирма + модель), у которых название модели заканчивается на "о":
string[] cars=Select(arr, car, car.Company+" "+car.Model, EndsWith(car.Model,'o'));
WriteLine(Join(", ", cars)); //Ford Mondeo, Kia Rio, Kia Sorento
class Car{
public string Model, Company;
New(string company, string model){
Model=model;
Company=company;
}
}
int Push(some[] arr, object value0, object value1 ...) 2 - добавляет один или более элементов в конец массива и возвращает новую длину массива. Поддерживает работу со списками, стеком и очередью. short[] arr=new short[]{10, 20, 30};
WriteLine(Push(arr, short\40, short\50)); //5
WriteLine(Join(' ', arr)); //10 20 30 40 50
//-----
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections");
Push(list, "Hello", "World", "Test"); //аргументы должны быть нужного типа (не будут конвертированы)
WriteLine(Join(' ', list)); //Hello World Test
int ConvPush(some[] arr, object value0, object value1 ...) 2 - добавляет один или более элементов в конец массива с конвертированием. Поддерживает работу со списками, стеком и очередью. date[] d=new date[]{Now()};
ConvPush(d, "06.09.2021", "07.09.2021"); //аргументы будут конвертированы в нужный тип
WriteLine(Join("; ", d)); //05.09.2021 14:28:07; 06.09.2021 0:00:00; 07.09.2021 0:00:00
//---------------------
object list=Create("System.Collections.Generic.List`1[System.DateTime]");
ConvPush(list, "05.09.2021", "06.09.2021", "07.09.2021");
WriteLine(Join("; ", list)); //05.09.2021 0:00:00; 06.09.2021 0:00:00; 07.09.2021 0:00:00
some Peek(some[] arr) 2 - возвращает последний элемент из массива. Поддерживает работу со списками, стеком и очередью. byte[] arr=new byte[]{10, 20, 30};
WriteLine(Peek(arr)); //30
//****List<string>******
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections");
list->AddRange(new string[]{"Hello", "World", "Test"});
WriteLine(Peek(list)); //Test
//*****Stack*****
object stack=Create("System.Collections.Stack, System.Collections.NonGeneric");
stack->Push("Hello");
stack->Push("World");
stack->Push("Test");
WriteLine(Peek(stack)); //Test
//*****Queue*****
object queue=Create("System.Collections.Queue, System.Collections.NonGeneric");
queue->Enqueue("Hello");
queue->Enqueue("World");
queue->Enqueue("Test");
WriteLine(Peek(queue)); //Hello
some Pop(some[] arr) 2 - возвращает и удаляет последний элемент из массива. Поддерживает работу со списками, стеком и очередью. byte[] arr=new byte[]{10, 20, 30};
WriteLine(Pop(arr)); //30
WriteLine(Join(' ', arr)); //10 20
some At(some[] arr) 2 - возвращает по индексу элемент из массива. Индекс может быть отрицательным. Поддерживает работу со списками. byte[] arr=new byte[]{10, 20, 30};
WriteLine(At(arr, -2)); //20
object ElementAt(object arr, int index) - возвращает по индексу элемент из любого объекта, реализующего интерфейс System.Collections.IEnumerable. Индекс не может быть отрицательным.object stack=Create("System.Collections.Stack, System.Collections.NonGeneric");
Push(stack, "hello", "world", "test");
WriteLine(ElementAt(stack, 1)); //world
object ToArray(object collection, object type, int size) 4 - создаёт массив из любого объекта, реализующего интерфейс System.Collections.IEnumerable. Желательно указывать размер массива.object stack=Create("System.Collections.Stack, System.Collections.NonGeneric");
Push(stack, "hello", "world", "test");
string[] arr:=stack.ToArray(string);
WriteLine(Join(' ', arr)); //test world hello
object ConvertArray(object arr, string type) 2 - Конвертирует массив в указанный тип.
short[] arr={10, 20, 30};
byte[] arr2:=ConvertArray(arr, byte);
WriteLine(Join(' ', arr2)); //10 20 30
object arr3=ConvertArray(arr, "System.UInt32"); //10 20 30
WriteLine(Join(' ', arr3));
WriteLine(arr3); //System.UInt32[]
object[] ToObjectArray(object arr, object type) 3 - создаёт из массива массив object[]. Можно указывать тип элементов для конвертирования. Работает только с массивами.int[] arr={10, 20, 30};
object[] arr2=ToObjectArray(arr, byte);
WriteLine(arr2); //System.Object[]
WriteLine(GetType(arr2[0])); //System.Byte
WriteLine(Join(' ', arr2)); //10 20 30
arr2=ToObjectArray(arr, "System.UInt32");
WriteLine(GetType(arr2[0])); //System.UInt32
WriteLine(Join(' ', arr2)); //10 20 30
arr2=ToObjectArray(arr); //без конвертирования
WriteLine(Join(' ', arr2)); //10 20 30
string str=ReadAllText("file.txt", "windows-1251");
str=ReadAllText("file.txt", 1251);
str=ReadAllText("file.txt", GetEncoding("windows-1251"));
void WriteAllText(string path, string text, string encoding) 4 - Записывает текст в файл (создаёт файл, если его нет), используя заданную кодировку. Кодировка по умолчанию - UTF-8 без BOM. Использует File.WriteAllText.
WriteAllText("file.txt", "текст", "windows-1251");
void AppendAllText(string path, string text, string encoding) 4 - Добавляет текст в файл в указанной кодировке, создавая файл, если он не существует. Кодировка по умолчанию - UTF-8 без BOM. Использует File.AppendAllText. WriteLine(GetEncoding("utf-8")); //System.Text.UTF8Encoding+UTF8EncodingSealed
void CopyFile(string sourceFileName, string destFileName, bool overwrite) 2 - Копирует существующий файл в новый файл. Использует File.Copy.
CopyFile(@"D:\files\test.txt", @"D:\files\test2.txt");
CopyFile("test.txt", "test2.txt"); // можно указывать относительный путь
CopyFile(@"D:\files\test.txt", @"D:\files\test2.txt", true); // перезаписывает файл
void MoveFile(string sourceFileName, string destFileName, bool overwrite) 2 - Перемещает указанный файл в новое расположение, предоставляя параметры для указания нового имени файла и перезаписи конечного файла, если он уже существует. Использует File.Move.
MoveFile(@"D:\files\test.txt", @"D:\files\test2.txt");
void DeleteFile(string path) - Удаляет указанный файл. Использует File.Delete.
DeleteFile(@"D:\files\test.txt");
void CreateDirectory(string path) - Создает каталог по заданному пути. Использует Directory.CreateDirectory.
CreateDirectory(@"D:\dir\newdir");
void DeleteDirectory(string path, bool recursive) 2 - Удаляет заданный каталог и при необходимости все подкаталоги. Использует Directory.Delete.
DeleteDirectory(@"D:\dir\test", true);
void MoveDirectory(string sourceDirName, string destDirName) - Перемещает файл или каталог со всем его содержимым в новое местоположение. Использует Directory.Move.
MoveDirectory(@"D:\dir\test", @"D:\dir\test2");
string[] GetFiles(string path, string searchPattern, bool includeSubdirectories) 3 - Возвращает имена файлов (включая пути) из указанного каталога, отвечающие условиям заданного шаблона поиска. Использует Directory.GetFiles.
string[] files = GetFiles(@"D:\files"); // берутся все файлы.
files = GetFiles(@"D:\files", "*.txt"); // берутся только txt-файлы.
files = GetFiles(@"D:\files", "", true); // берутся все файлы, в том числе из вложенных папок.
string GetFileName(string path) - Возвращает из пути имя файла с расширением. Использует Path.GetFileName.
string fileName = GetFileName(@"D:\files\test.txt"); // test.txt
string GetFileNameWithoutExtension(string path) - Возвращает из пути имя файла без расширения. Использует Path.GetFileNameWithoutExtension.
string fileName = GetFileNameWithoutExtension(@"D:\files\test.txt"); // test
string GetExtension(string path) - Возвращает расширение указанной строки пути (включая точку "."). Использует Path.GetExtension.
string fileExt = GetExtension(@"D:\files\test.txt"); // .txt
string[] GetDirectories(string path, string searchPattern, bool includeSubdirectories) 3 - Возвращает имена подкаталогов, соответствующих указанным критериям. Использует Directory.GetDirectories.
string[] dirs = GetDirectories(@"D:\dir"); // берутся все папки.
long FileSize(string path) - Возвращает размер файла (байт). Использует FileInfo.Length. WriteLine(CombinePath("D:", "test", "hello.txt")); //D:\test\hello.txt
WriteLine(CombinePath(@"D:\dir", "test", "hello.txt")); //D:\dir\test\hello.txt
object thread = Thread(WriteLine("")); //создание потока с ссылкой на функцию WriteLine(object)
object ThreadByFuncRef(object funcRef, string name, bool isBackground) 4 - создаёт поток из ссылки на функцию.
object thread = ThreadByFuncRef(FuncRef(WriteLine(""))); //ссылка на функцию передаётся первым аргументом
void StartThread(object thread, params object[] args) 2 - запускает поток, в котором по ссылке вызывается функция с передачей аргументов. Использует Thread.Start.
object thread = Thread(WriteLine("")); //создание потока с ссылкой на функцию WriteLine(object)
StartThread(thread, "Hello!"); //запуск потока с передачей функции WriteLine строки "Hello!"
Wait(thread); //ожидание завершения потока
ReadKey("Press some key to exit");
object LocalThread(expression, string name, bool isBackground) 4 - создаёт локальный поток, который может работать с переменными из области создания. Использует класс System.Threading.Thread. string s="Hello!";
object thread = LocalThread(WriteLine(s));
StartThread(thread);
//Hello!
ReadKey();
string s="Hello!";
object thread = LocalThread(s="Test!");
StartThread(thread);
Wait(thread);
WriteLine(s); //Test!
ReadKey();
object LocalThreadByExpr(object expr, string name, bool isBackground) 4 - создаёт локальный поток из выражения. string s="Hello!";
object thread = LocalThreadByExpr(Expr(WriteLine(s)));
StartThread(thread);
//Hello!
ReadKey();
object RunLocalThread(expression, string name, bool isBackground) 3 - Создаёт и запускает локальный поток из выражения.object t=RunLocalThread(WriteLine("OK!"));
Wait(t);
//OK!
object RunThread(expression, string name, bool isBackground) 3 - Создаёт и запускает поток с выражением, в которое автоматически упаковываются все локальные переменные. string s="Test";
object t=RunThread(WriteLine("s="+s));
Wait(t);
//s=Test
bool IsAlive(object thread) - Возвращает значение, показывающее статус выполнения текущего потока. Использует Thread.IsAlive. object mre=Create("System.Threading.ManualResetEvent", false);
WriteLine("Start 3 named threads that block on a ManualResetEvent:\n");
for(int i = 0; i <= 2; i++)
{
object t = Thread(ThreadProc(), "Thread_" + i);
StartThread(t);
}
Sleep(500);
WriteLine("\nWhen all three threads have started, press Enter to call SetEventWaitHandle(mre)" +
"\nto release all the threads.\n");
ReadLine();
SetEventWaitHandle(mre);
Sleep(500);
WriteLine("\nWhen a ManualResetEvent is signaled, threads that call Wait(mre)" +
"\ndo not block. Press Enter to show this.\n");
ReadLine();
for(int $i = 3; i <= 4; i++)
{
object $t = Thread(ThreadProc(), "Thread_" + i);
StartThread(t);
}
Sleep(500);
WriteLine("\nPress Enter to call ResetEventWaitHandle(mre), so that threads once again block" +
"\nwhen they call Wait().\n");
ReadLine();
ResetEventWaitHandle(mre);
// Start a thread that waits on the ManualResetEvent.
object $t = Thread(ThreadProc(), "Thread_5");
StartThread(t);
Sleep(500);
WriteLine("\nPress Enter to call SetEventWaitHandle(mre) and conclude the demo.");
ReadLine();
SetEventWaitHandle(mre);
ReadKey();
void ThreadProc()
{
string name = ThreadName();
WriteLine(name + " starts and calls Wait(mre)");
Wait(mre);
WriteLine(name + " ends.");
}
object Task(object func, params object[] args) - Создаёт задачу. Ссылка на функцию для задачи создаётся из первого аргумента. Использует System.Threading.Tasks.Task.
object task=Task(WriteLine(""), "Hello!");
object TaskByFuncRef(object funcRef, params object[] args) - Создаёт задачу из ссылки на функцию. object task=TaskByFuncRef(FuncRef(WriteLine("")), "Hello!");
void StartTask(object task) - Запускает задачу. Использует Task.Start. object task=Task(Test(int\), 5);
StartTask(task);
WriteLine(TaskResult(task)); //10
//Теперь с LocalTask:
task=LocalTask(Test(5));
StartTask(task);
WriteLine(TaskResult(task)); //10
//Из выражения:
task=LocalTaskByExpr(Expr(Test(5)));
StartTask(task);
WriteLine(TaskResult(task)); //10
ReadKey();
int Test(int x){
return x*2;
}
object TaskException(object task) - Возвращает объект AggregateException, который привел к преждевременному завершению задачи Task. Использует Task.Exception. object cts=CancellationTokenSource();
object token=CancellationToken(cts);
object task=Task(Test(object\), token);
StartTask(task);
Sleep(5000);
Cancel(cts);
Wait(task);
WriteLine("END");
//1 2 3 4 5 END
//Пример с автоматической отменой через 5 секунд
cts=CancellationTokenSource(5000);
token=CancellationToken(cts);
task=Task(Test(object\), token);
StartTask(task);
Wait(task);
WriteLine("END");
//1 2 3 4 5 END
ReadKey();
Test(object cts){
int n;
do{
Write((++n)+" ");
Sleep(1000);
}while(!IsCancellationRequested(cts));
}
object RunLocalTask(expression) - Создаёт и запускает задачу из выражения. object t=RunLocalTask(WriteLine("OK!"));
Wait(t);
//OK!
object RunTask(expression) - Создаёт и запускает задачу с выражением, в которое автоматически упаковываются все локальные переменные. string s="Test";
object t=RunTask(WriteLine("s="+s));
Wait(t);
//s=Test
object t=Timer(OnTimedEvent(object\, object\), 1000, true); //создание и запуск таймера
//OnTimedEvent! SignalTime: 29.08.2021 10:46:28
//OnTimedEvent! SignalTime: 29.08.2021 10:46:29
//OnTimedEvent! SignalTime: 29.08.2021 10:46:30
//...
ReadKey();
OnTimedEvent(object source, object e){
WriteLine("OnTimedEvent! SignalTime: " + e->SignalTime);
}
Методу таймера можно передавать аргументы:
int x=555;
string str="test";
object t=Timer(OnTimedEvent(object\, object\, int\, string\), 1000, true, true, true, x, str); //дополнительные аргументы x и str указываются в конце
//OnTimedEvent! SignalTime: 29.08.2021 14:04:12; v: 555; s: test
//OnTimedEvent! SignalTime: 29.08.2021 14:04:13; v: 555; s: test
//OnTimedEvent! SignalTime: 29.08.2021 14:04:14; v: 555; s: test
//...
ReadKey();
OnTimedEvent(object source, object e, int v, string s){
WriteLine("OnTimedEvent! SignalTime: " + e->SignalTime + $"; v: {v}; s: {s}");
}
object TimerByFuncRef(object funcRef, int interval, bool enabled, bool autoReset) 5 - создаёт таймер из ссылки на функцию.object timer=LocalTimer(WriteLine(TickCount()), 1000, true); // каждую секунду будет выводиться время, истекшее с момента загрузки системы.
ReadKey();
object LocalTimerByExpr(object expr, int interval, bool enabled, bool autoReset) 4 - создаёт локальный таймер из выражения.
object timer=LocalTimerByExpr(Expr(WriteLine(TickCount())), 1000, true);
void StartTimer(object timer) - запускает таймер. Использует Timer.Start. object timer=LocalTimer(WriteLine(TickCount()), 1000);
StartTimer(timer);
Sleep(3000);
StopTimer(timer);
//Таймер будет выключен через 3 сек.
ReadKey();
object RunTimer(expression, int interval, bool autoReset, bool nonSync) 3 - Создаёт и запускает таймер с выражением, в которое автоматически упаковываются все локальные переменные. int n;
object t=RunTimer(Write((n++)+" "), 1000, true, true);
Sleep(5000);
StopTimer(t);
//0 1 2 3 4
string[] result=RegexMatches("Who writes these notes?", @"\b\w+es\b");
WriteLine(Join(", ",result)); // writes, notes
result=RegexMatches("Who writes these NOTES?", @"\b\w+es\b", 1);
WriteLine(Join(", ",result)); // writes, NOTES
object options=ToEnum("IgnoreCase", "System.Text.RegularExpressions.RegexOptions, System");
result=RegexMatches("Who writes these NOTES?", @"\b\w+es\b", options);
WriteLine(Join(", ",result)); // writes, NOTES
string RegexReplace(string input, string pattern, string replacement, int options) 3 - В указанной входной строке заменяет строки, соответствующие шаблону регулярного выражения, указанной строкой замены. Использует Regex.Replace.
string pattern=@"при(\w*)";
string result=RegexReplace("привет мир принцесса", pattern, "ОК");
WriteLine(result); // ОК мир ОК
result=RegexReplace("привет мир Принцесса", pattern, "ОК", 1);
WriteLine(result); // ОК мир ОК
object options=ToEnum("IgnoreCase", "System.Text.RegularExpressions.RegexOptions, System");
result=RegexReplace("привет мир Принцесса", pattern, "ОК", options);
WriteLine(result); // ОК мир ОК
Point point=new Point(15, 77);
string js=ToJson(point);
WriteLine(js); // {"x":15,"y":77}
class Point{
public int x, y;
New(int x, int y){
this.x=x;
this.y=y;
}
}
object FromJson(string json, object type) 6 - Выполняет синтаксический анализ текста, представляющего одно значение JSON, в экземпляр типа, заданного параметром type. Использует JsonSerializer.Deserialize. string js="{\"x\":15,\"y\":77}";
Point point2=FromJson(js,Point);
WriteLine(point2.x+"; "+point2.y); // 15; 77
По умолчанию обрабатываются только публичные переменные. Чтобы приватные тоже обрабатывались, нужно задать withPrivate=true (работает только для своих типов).
string js=ToJson(point, true);
Point point2=FromJson(js, Point, true);
Через сериализацию и десериализацию можно скопировать данные из объекта одного типа в другой:
Foo f=new Foo();
Bar b=FromJson(ToJson(f), Bar);
Пример с объектом типа System.Drawing.Point:
// Создаём объект Point
object pointType=typeof("System.Drawing.Point, System.Drawing");
object point=Create(pointType, 10, 20);
string js=ToJson(point); //сериализация
object point2=FromJson(js, pointType); //десериализация
//Теперь в point2 находится объект Point
WriteLine("Type: "+GetType(point2)); // Type: System.Drawing.Point
WriteLine(point2); // {X=10,Y=20} // результат Point.ToString()
WriteLine(point2->Y); //20
string str=Fetch("http://overscript.org/");
string headers="Referer: http://en.wikipedia.org/wiki/Main_Page\r\nUser-Agent: Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1";
string str=Fetch("http://overscript.org/", headers);
string str=Fetch("http://overscript.org/",, "windows-1251", 20000, "MaxAutomaticRedirections=5, AllowAutoRedirect=true");
string str=Fetch("http://overscript.org/",,,,, "someValue=Hello&someValue2=World"); // POST-запрос
object handler=Create("System.Net.Http.HttpClientHandler, System.Net.Http");
handler->AllowAutoRedirect=true;
handler->MaxAutomaticRedirections=7;
handler->SslProtocols=ToEnum("Tls12", "System.Security.Authentication.SslProtocols, System");
string str=Fetch("http://overscript.org/",,, 5000, handler);
WriteLine(LoadPage("http://overscript.org/"));
ReadKey();
//Функция ниже получает страницу без http-заголовка
string LoadPage(string url){
try{
string data=Fetch(url);
int i=IndexOf(data, "\r\n\r\n");
if(i>=0) data=Substring(data, i+4);
return data;
}catch{
WriteLine("Не удалось открыть "+url+" ("+exMessage+")");
}
}
string UrlEncode(string text, string encoding) 3 - Кодирует строку URL-адреса, используя указанную кодировку (по умолчанию utf-8). Использует HttpUtility.UrlEncode. WriteLine(UrlEncode("Привет")); // %d0%9f%d1%80%d0%b8%d0%b2%d0%b5%d1%82
WriteLine(UrlEncode("Привет", "windows-1251")); // %cf%f0%e8%e2%e5%f2
string UrlDecode(string text, string encoding) 3 - Преобразует строку, закодированную для передачи в URL-адресе, в декодированную строку, используя указанную кодировку (по умолчанию utf-8). Использует HttpUtility.UrlDecode. WriteLine(UrlDecode("%d0%9f%d1%80%d0%b8%d0%b2%d0%b5%d1%82")); // Привет
WriteLine(UrlDecode("%cf%f0%e8%e2%e5%f2", "windows-1251")); // Привет
object Uri(string uri) - Создаёт из строки новый экземпляр класса Uri. object uri=Uri("https://www.google.com/");
WriteLine(uri->Host); //www.google.com
string GetAbsoluteUri(string baseUri, string relativeUri, bool pathAndQuery) 2 - Получает абсолютный универсальный код ресурса. Если pathAndQuery задать true, то возвращает свойства AbsolutePath и Query, разделенные вопросительным знаком (?). Использует Uri.AbsoluteUri и Uri.PathAndQuery. WriteLine(GetAbsoluteUri("http://site.com/hello/", "page.php?q=test")); //http://site.com/hello/page.php?q=test
WriteLine(GetAbsoluteUri("http://site.com/hello/", "page.php?q=test", true)); // /hello/page.php?q=test
WriteLine(Now()); // 22.02.2021 20:03:30 // локальная дата и время
WriteLine(Now(true)); // 22.02.2021 17:03:30 // глобальная дата и время
WriteLine(Now(,true)); // 22.02.2021 0:00:00 // локальная дата без времени
WriteLine(Now(true,true)); // 22.02.2021 0:00:00 // глобальная дата без времени
date DateAdd(date d, double num, char interval) 2 - Возвращает значение, содержащее дату и время, к которым был добавлен заданный период времени. interval указывает способ определения и форматирования интервалов дат (y - год, M - месяц, d - день, h - час, m - минута, s - секунда, f - миллисекунда). interval по умолчанию 'd' (день).date d:="18.02.2021";
WriteLine(DateAdd(d, 10, 's')); // 18.02.2021 0:00:10 // увеличиваем дату на 10 секунд
WriteLine(DateAdd(d, 5, 'd')); // 23.02.2021 0:00:00 // увеличиваем дату на 5 дней
WriteLine(DateAdd(d, 2, 'M')); // 18.04.2021 0:00:00 // увеличиваем дату на 2 месяца
double DateDiff(date d1, date d2, char dateInterval) 2 - Возвращает значение, указывающее количество интервалов времени между двумя датами. interval по умолчанию 'd' (день).date d1:="18.02.2021";
date d2=DateAdd(d1,1,'y'); // увеличиваем дату на 1 год
WriteLine(DateDiff(d1,d2,'y')); // 1
WriteLine(DateDiff(d1,d2,'M')); // 12
WriteLine(DateDiff(d1,d2,'d')); // 365
WriteLine(DateDiff(d1,d2,'h')); // 8760
WriteLine(DateDiff(d1,d2,'m')); // 525600
WriteLine(DateDiff(d1,d2,'s')); // 31536000
WriteLine(DateDiff(d1,d2,'f')); // 31536000000
date ToUniversalTime(date d) - Преобразует значение текущего объекта DateTime во время UTC. Использует DateTime.ToUniversalTime. object type=GetType("Test");
WriteLine(type); // System.String
byte n=123;
WriteLine(GetType(n)); // System.Byte
string GetTypeName(object obj) 2 - Возвращает имя типа текущего экземпляра. Использует Object.GetType. string str="test";
WriteLine("Type name: "+GetTypeName(str)+"; full name: "+GetTypeName(str, true)); // Type name: String; full name: System.String
object sb=Create("System.Text.StringBuilder", "test");
WriteLine("Type name: "+GetTypeName(sb)+"; full name: "+GetTypeName(sb, true)); // Type name: StringBuilder; full name: System.Text.StringBuilder
Пример в методе, принимающем объекты разных типов:
Foo f=new Foo();
Bar b=new Bar();
Test(f); //Processing Foo. Type: App.Foo
Test(b); //Processing Bar. Type: App.Bar
Test(object obj){
switch(GetType(obj)){
case typeof(Foo):
WriteLine("Processing Foo. Type: "+GetTypeName(obj, true));
break;
case typeof(Bar):
WriteLine("Processing Bar. Type: "+GetTypeName(obj, true));
break;
}
}
class Foo{}
class Bar{}
В примере выше typeof используется в case, что не работает в C#, но в OverScript результат typeof это object-литерал, поэтому всё сработает как надо.object obj=123;
WriteLine(GetType(obj)); // System.Int32
obj=ChangeType(obj, "System.Byte");
WriteLine(GetType(obj)); // System.Byte
obj=ChangeType(obj,typeof("System.Int64"));
WriteLine(GetType(obj)); //System.Int64
object Create(string typeName, params object[] args) 4 - Возвращает объект указанного типа, если тип предполагает создание экземпляров. args - аргументы, которые передаются конструктору типа. Использует Activator.CreateInstance. object sb=Create("System.Text.StringBuilder", "test");
WriteLine(sb); // "test"
sb=Create(typeof("System.Text.StringBuilder"), "hello"); //вместо имени типа передаём сам тип
WriteLine(sb); // выведет "hello"
object CreateFrom(string file, string typeName, params object[] args) 4 - Загружает сборку из файла и возвращает из неё объект указанного типа, если тип предполагает создание экземпляров. Использует Assembly.LoadFrom и Activator.CreateInstance. object obj=CreateFrom(@"D:\lib\TestLib.dll", "TestClass");
//Или так:
object asm=LoadAssemblyFrom(@"D:\lib\TestLib.dll"); // сначала загружаем сборку
obj=CreateFrom(asm, "TestClass"); // подаём на вход сборку, а не имя файла
object GetTypeByName(string typeName) 3 - Возвращает тип с указанным именем. Можно задать файл или сборку, в которой искать тип. Использует Type.GetType. object type=GetTypeByName("System.Text.StringBuilder");
object sb=Create(type, "test");
WriteLine(sb); // "test"
object LoadAssembly(string assemblyName) - Загружает сборку с указанным именем. Использует Assembly.Load. object asm=LoadAssembly("System");
WriteLine(asm); // System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
object LoadAssemblyFrom(string file) - Загружает сборку из файла. Использует Assembly.LoadFrom. WriteLine(LoadAssemblyFrom(@"D:\lib\Test.dll")); // Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
object InvokeMember(object type, string member, string bindingFlags, object binder, object obj, params object[] args) 6 - Вызывает определенный член заданного типа. Если type пропустить, то будет браться тип объекта. bindingFlags можно задавать строкой или числом: "InvokeMethod" - 256, "GetProperty" - 4096, "SetProperty" - 8192, "GetField" - 1024, "SetField" - 2048. Использует Type.InvokeMember.object type=typeof("System.Text.StringBuilder");
object sb=Create(type, "Hello ");
InvokeMember(type, "Append", "InvokeMethod",, sb, "World!");
InvokeMember(, "Append", 256,, sb, " It"); // тип можно не указывать (будет взят у sb)
InvokeMember(type, "Append", ToEnum("InvokeMethod", "System.Reflection.BindingFlags"),, sb, " Works!");
WriteLine(sb); //Hello World! It Works!
object InvokeMethod(object obj, string member, params object[] args) - Вызывает метод заданного объекта или типа. Использует Type.GetMethod и MethodBase.Invoke.object obj=CreateFrom(@"D:\lib\Test.dll", "SomeType"); //создаём экземпляр класса SomeType.
object v=InvokeMethod(obj, "Test", 2, 3); //вызывает метод Test объекта obj с передачей аргументов (2 и 3).
//Синтаксический сахар для InvokeMethod:
v=obj->Test(2, 3);
При применении на типе, чтобы вызвать метод у типа типа (type.GetType()), нужно к имени метода добавить в начало символ @:
object type=typeof("System.IO.Stream");
bool b:=InvokeMethod(type, "@IsAssignableFrom", typeof("System.IO.MemoryStream, System.IO"));
WriteLine(b); //True
object GetMemberValue(object obj, string member, params object[] indexes) - Получает значение свойства или поля, либо MemberInfo заданного члена, если он не свойство или поле. indexes - массив индексов, которые нужны, если вы получаете значение индексатора. Использует Type.GetField, Type.GetProperty и PropertyInfo.GetValue, FieldInfo.GetValue.object obj=CreateFrom(@"D:\lib\Test.dll", "SomeType"); //создаём экземпляр класса SomeType.
object v=GetMemberValue(obj, "SomeProp"); //получение значения свойства SomeProp.
v=GetMemberValue(obj, "Item", 2); //получение значения по индексу. Item - индексатор (свойство по умолчанию).
//Синтаксический сахар для GetMemberValue:
v=obj->SomeProp;
v=obj->Item[2]; //индексатор
//Пример использования синтаксического сахара с List-ом:
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections"); //создаём List<string>
list->AddRange(new string[]{"Hello", "World", "Test"}); //добавляем 3 элемента: "Hello", "World" и "Test".
for(int i=0; i<Length(list); i++) WriteLine(list->Item[i]); //вывод всех элементов
//Hello
//World
//Test
При применении на типе, чтобы считать свойство/поле типа типа (type.GetType()), нужно к имени члена добавить в начало символ @:
object type=typeof("System.IO.Stream");
WriteLine(GetMemberValue(type, "@IsValueType")); //False
void SetMemberValue(object obj, string member, object value, params object[] indexes) - Задаёт значение свойства, поля или события (AddEventHandler). indexes - массив индексов, которые нужны, если вы задаёте значение индексатора. Использует Type.GetField, Type.GetProperty и PropertyInfo.SetValue, FieldInfo.SetValue.object obj=CreateFrom(@"D:\lib\Test.dll", "SomeType"); //создаём экземпляр класса SomeType.
SetMemberValue(obj, "SomeProp", 10); //установка значения свойства SomeProp.
SetMemberValue(obj, "Item", 10, 2); //установка значения по индексу. Item - индексатор (свойство по умолчанию).
//Синтаксический сахар для SetMemberValue:
obj->SomeProp=10;
obj->Item[2]=10; //индексатор
При применении на типе, чтобы записать свойство/поле типа типа (type.GetType()), нужно к имени члена добавить в начало символ @.
//В этом примере перехватывается нажатие Ctrl+C (прерывание процесса)
object d = Delegate(OnConsoleCancel(null, null), typeof("System.ConsoleCancelEventHandler, System.Console")); //создаём делегат ConsoleCancelEventHandler
//Для вызова SetMemberValue используем стрелочку
typeof("System.Console, System.Console")->CancelKeyPress += d; // CancelKeyPress - это событие, а присваивание ему d - это добавление делегата. В C# было бы: Console.CancelKeyPress += d;
//"System.Console, System.Console" - это упрощенное AssemblyQualifiedName для System.Console (https://docs.microsoft.com/ru-ru/dotnet/api/system.type.assemblyqualifiedname?view=net-5.0)
WriteLine("Press Ctrl+C...");
ReadKey();
OnConsoleCancel(object sender, object args){
WriteLine("\nThe read operation has been interrupted.");
WriteLine(" Key pressed: "+args->SpecialKey);
WriteLine(" Cancel property: "+args->Cancel);
WriteLine("Setting the Cancel property to true...");
args->Cancel = true;
WriteLine(" Cancel property: "+args->Cancel);
WriteLine("The read operation will resume...\n");
}
object GetMember(object obj, string member) - Возвращает MemberInfo с указанным именем (первый подходящий). Если такого члена нет, то возвращается null. Использует Type.GetMember.object type=typeof("System.IO.Stream");
WriteLine(GetMember(type, "@IsValueType")); //Boolean IsValueType
Обратите внимание, что в C# Type.GetMember возвращает массив всех найденных членов, а не первый из них. const object Math=typeof("System.Math");
WriteLine(GetMember(Math, "Ceiling")); //Double Ceiling(Double)
object[] arr=GetMembers(Math, "Ceiling");
WriteLine(Join("; ", arr)); //Double Ceiling(Double); System.Decimal Ceiling(System.Decimal)
object GetValue(object memberInfo, object obj, params object[] indexes) 3 - Возвращает значение свойства или поля. indexes - массив индексов, которые нужны, если вы получаете значение индексатора. Использует PropertyInfo.GetValue и FieldInfo.GetValue.object env=typeof("System.Environment"); //получаем тип System.Environment
object m=GetMember(env, "TickCount"); //получаем из System.Environment свойство TickCount
WriteLine(m); //Int32 TickCount
WriteLine(GetValue(m)); //867103296
object point=Create("System.Drawing.Point, System.Drawing", 10, 20); //создаём Point с X: 10, Y: 20
m=GetMember(point, "X"); //получаем свойство X
WriteLine(m); //Int32 X
WriteLine(GetValue(m, point)); //10
SetValue(m, point, 15); //меняем свойство X на 15
WriteLine(GetValue(m, point)); //15
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections"); //создаём List<string>
list->AddRange(new string[]{"Hello", "World", "Test"}); //добавляем 3 элемента: "Hello", "World" и "Test".
m=GetMember(list, "Item"); //получаем индексатор
WriteLine(GetValue(m, list, 2)); //Test //это элемент с индексом 2
SetValue(m, list, "OK", 2); //теперь меняем Test на OK
WriteLine(GetValue(m, list, 2)); //OK //элемент с индексом 2 изменился
object GetMethod(object obj, string member, params object[] types) - Возвращает MemberInfo для метода с указанными именем и типами аргументов. Можно использовать как на типе, так и на экземпляре. Использует Type.GetMethod.object type=typeof("System.IO.Stream");
object m=GetMethod(type, "@IsAssignableFrom", typeof("System.Type"));
//с type.GetType(): object m=GetMethod(GetType(type), "IsAssignableFrom", typeof("System.Type"));
WriteLine(m); //Boolean IsAssignableFrom(System.Type)
WriteLine(Invoke(m, type, typeof("System.IO.MemoryStream, System.IO"))); //True
//то же самое можно так: WriteLine(type->@IsAssignableFrom(typeof("System.IO.MemoryStream, System.IO"))); //True
//посмотрим, как видит стрелку интерпретатор:
//WriteLine(Expr(type->@IsAssignableFrom(typeof("System.IO.MemoryStream, System.IO")))); //@InvokeMethod(type,"@IsAssignableFrom",#System.IO.MemoryStream#)
object Invoke(object memberInfo, object obj, params object[] args) - Выполняет метод. Использует MethodBase.Invoke.object math=typeof("System.Math");
object m=GetMethod(math, "Max", int, int); //в OverScript тип можно можно писать как typeof(int) (литерал), так и int (не литерал)
WriteLine(m); //Int32 Max(Int32, Int32)
WriteLine(Invoke(m,, 2, 3)); //3 //объект пропущен т.к. метод статический
object sb=Create("System.Text.StringBuilder", "test");
object m=GetMethod(sb, "Append", string);
WriteLine(m); //System.Text.StringBuilder Append(System.String)
WriteLine(Invoke(m, sb, " hello")); //test hello
some TInvoke(object methodInfo, type, object obj, params object[] args) 3 - Выполняет метод, возвращает значение конкретного типа. Конвертирования результата не делает.object Math=typeof("System.Math");
object m=GetMethod(Math, "Max", int, int);
WriteLine(m); //Int32 Max(Int32, Int32)
int x=TInvoke(m, int, , 2, 3); //тут нужно писать именно int, а не typeof(int)
WriteLine(x); //3
some TGetValue(object memberInfo, type, object obj, params object[] indexes) 3 - Возвращает значение свойства или поля, но не object, а конкретного типа, который задаётся вторым аргументом. indexes - массив индексов, которые нужны, если вы получаете значение индексатора. object sb=Create("System.Text.StringBuilder", "test");
object m=GetMember(sb, "Length");
WriteLine(m); //Int32 Length
WriteLine(TGetValue(m, int, sb)); //4 //тут нужно писать именно int, а не typeof(int)
void AddEventHandler(object eventInfo, object obj, object delegate) - Добавляет обработчик событий в источник события. Использует EventInfo.AddEventHandler.int x, y;
object e=Expr(WriteLine(x+y));
WriteLine(e); //WriteLine(x+y)
WriteLine(GetType(e)); //OverScript.Expr
//можно указать какие переменные вовлеч в выражение
e=Expr(WriteLine(x+y), x, y);
object Eval(object expr) 2 - Выполняет выражение. int x=2, y=3;
object e=Expr(WriteLine(x+y));
Eval(e); //5
e=Expr(x+y);
int sum=Eval(e, int); //тип нужно указывать именно int, а не typeof(int)
WriteLine(sum); //5
object SetVarScopeKind(object expr, string kind, var0, var1, var2, ...) - Меняет тип области видимости переменных в выражении. Типы: "Local" - локальная, "Static" - статическая, "Ref" - ссылка, "This" - экземплярная. Возвращает не новое выражение, а ссылку на исходное (изменённое).int x=2, y=3;
object e=Expr(WriteLine(x+y));
SetVarScopeKind(e, "Static", x, y);
object CopyExpr(object expr) - Копирует выражение.int x=2, y=3;
object e=Expr(WriteLine(x+y));
object e2=CopyExpr(e);
object Involve(object expr, var0, var1, var2, ...) - Вовлекает переменные в выражение. Возвращает не новое выражение, а ссылку на исходное (изменённое).int x=2, y=3;
object e=Expr(WriteLine(x+y));
Involve(e, x, y);
object Box(object expr, var0, var1, var2, ...) - Упаковывает переменные в выражение. Возвращает не новое выражение, а ссылку на исходное (изменённое).int x=2, y=3;
object e=Expr(WriteLine(x+y));
Box(e, x, y);
object BoxAll(object expr) - 2 Упаковывает в выражение значения всех или только локальных (второй аргумент - true) переменных. Упаковываются в том числе ранее вовлечённые переменные (если упаковываются все, а не только локальные). Возвращает не новое выражение, а ссылку на исходное (изменённое).int x=2, y=3;
object e=Expr(WriteLine(x+y));
BoxAll(e);
object FixOrigExpr(object expr) - Запоминает состояние выражения. Возвращает не новое выражение, а ссылку на исходное.int x=2, y=3;
object e=Expr(WriteLine(x+y));
FixOrigExpr(e);
object OrigExpr(object expr) 2 - Возвращает копию запомненного ранее состояния выражения.int x=2, y=3;
object e=Expr(WriteLine(x+y));
FixOrigExpr(e);
object e2=OrigExpr(e);
//можно указать, какие переменные вовлечь в новое выражение
e2=OrigExpr(e, x, y);
object Renew(object expr, bool hot) 2 - Обновляет выражение. Параметром hot можно задать, чтобы делалось горячее обновление, при котором происходит замена членов корневого выражения, а не простая смена ссылки.object e=Expr(Write("Hello! "));
object timer=LocalTimerByExpr(e, 1000, true);
Sleep(3000);
Renew(e, Expr(Write("Test! ")), true); //true указывает, что нужно сделать горячее обновление
Sleep(3000);
StopTimer(timer);
//Hello! Hello! Hello! Test! Test! Test!
WriteLine(Is(5, int)); //True
WriteLine(Is(5, short)); //False
WriteLine(Is(5, "System.Int32")); //True
object pointType=typeof("System.Drawing.Point, System.Drawing");
object point=Create(pointType, 10, 20);
WriteLine(Is(point, pointType)); //True
WriteLine(Is(point, typeof("System.Drawing.Rectangle, System.Drawing"))); //False
object ms=Create("System.IO.MemoryStream, System.IO");
WriteLine(Is(ms, typeof("System.IO.Stream"))); //True т.к. MemoryStream наследует от Stream
Foo f=new Foo();
WriteLine(Is(f, Foo)); //True
WriteLine(Is(f, Bar)); //False
Baz b=new Baz();
WriteLine(Is(b, Foo)); //True т.к. Baz наследует от Foo
class Foo{}
class Bar{}
class Baz:Foo{}
object As(object obj, string type) 3 - преобразует результат выражения в указанный тип. Если такое преобразование невозможно, возвращает null. Использует Type.IsInstanceOfType и Convert.ChangeType.
Bar b=new Bar();
Foo f=As(b, Foo);
WriteLine(f==null ? "NULL" : f); //NULL
Baz bz=new Baz();
f=As(bz, Foo);
WriteLine(f==null ? "NULL" : f); //Instance of Baz
class Foo{}
class Bar{}
class Baz:Foo{}
object ms=Create("System.IO.MemoryStream, System.IO");
object s=As(ms, "System.IO.Stream");
WriteLine(s==null ? "NULL" : s); //System.IO.MemoryStream
object obj=As(555, long);
WriteLine(obj==null ? "NULL" : obj+" "+GetType(obj)); //555 System.Int64
obj=As(555, "System.IO.Stream");
WriteLine(obj==null ? "NULL" : obj+" "+GetType(obj)); //NULL
object Clone(object obj, string type) 3 - создаёт копию объекта (поверхностное копирование). Можно копировать не только объекты своих типов, но и .NET-овских типов (происходит копирование полей через Reflection).
Bar b=new Bar(10, 20);
Bar b2=Clone(b, Bar);
b2.Print(); //Bar: 10; 20
WriteLine(GetType(b2)); //App.Bar
Foo f=Clone(b, Foo);
f.Print(); //Foo: 10
WriteLine(GetType(f)); //App.Foo
Baz bz=Clone(b, Baz); //Unable to clone object. The object does not inherit from Baz.
class Foo{
public int X;
New(int x){X=x;}
public Print(){WriteLine("Foo: "+X);}
}
class Bar:Foo{
public int Y;
New(int x, int y){
X=x;
Y=y;
}
public Print(){WriteLine("Bar: "+X+"; "+Y);}
}
class Baz{}
object type=typeof("System.Drawing.Point, System.Drawing");
object point=Create(type, 10, 20);
object point2=Clone(point, type);
WriteLine(point2->X+"; "+point2->Y); //10; 20
int Rand(int min, int max) - Генерирует случайное число. Использует Random.Next. int randNum=Rand(10,20); // случайное целое число между 10 и 20 (включительно)
//Вывод 5 случайных чисел от 0 до 10:
for(int i=0; i<5; i++) Write(Rand(0,10)+" "); //6 4 1 10 0
int TickCount() - Возвращает время, истекшее с момента загрузки системы (в миллисекундах). Использует Environment.TickCount. int t=TickCount();
WriteLine(t); // 1658266859
generalType If(bool condition, some trueValue, some falseValue) - Возвращает значение второго аргумента, если условие condition - true; в противном случае возвращается значение третьего аргумента. Тип возвращаемого значения - тип значения trueValue и falseValue (если они разные, то будет больший тип).
int n = If(5>4, 777, 123); // 777
string str = If(5==4, "hello", "world"); // "world"
//можно написать так:
//string str = 5==4 ? "hello" : "world";
some IfNotNull(object obj, some value) - Возвращает значение второго аргумента, если первый не null.
WriteLine(IfNotNull("test", "OK")); //OK
WriteLine(IfNotNull(null, "OK")==null); //True
void For(int start, int stop, int step, int counter, action0, action1, action2, ...) - Выполняет действия в цикле от start до stop (включительно). Аргумент counter - int-переменная в которую на каждой итерации записывается текущее значение счётчика. step - величина, на которую counter увеличивается каждый раз. Значение step может быть отрицательным.
//Заполнение массива и вывод всех значений
int[] arr=new int[10];
For(0, Length(arr)-1, 1, int i, arr[i]=i, Write(arr[i]+" ")); //заполняет массив и выводит от 0 до 9
WriteLine();
//Вывести от 0 до 20 с шагом 2
For(0, 20, 2, int x, Write(x+" ")); // выводит: 0 2 4 6 8 10 12 14 16 18 20
WriteLine();
//Вывести от 10 до 5 с шагом -1
For(10, 5, -1, i, Write(i+" ")); //10 9 8 7 6 5
WriteLine();
//Вывести 5 случайных чисел
For(1, 5, 1, , Write(Rand(10,100)+" ")); //87 46 96 46 67
ReadKey();
void ForEach(some[] array, some var, action0, action1, ...) 2 - Выполняет итерацию по элементам массива или любой перечислимой коллекции.
short[] arr=new short[]{10, 20, 30};
int n;
ForEach(arr, short v, WriteLine(n+") "+v), n++);
//0) 10
//1) 20
//2) 30
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections");
list->AddRange(new string[]{"Hello", "World", "Test"});
n=0;
ForEach(list, string item, WriteLine(n+") "+item), n++);
//0) Hello
//1) World
//2) Test
void While(bool condition, action0, action1, ...) - Выполняет действия в цикле пока condition равен true.
int i;
While(i<5, i++, Write(i+" ")); // 1 2 3 4 5
void DoWhile(bool condition, action0, action1, ...) - Как While, только условие проверяется после действий.
int i;
DoWhile(i>0, Write(i)); // 0
WriteLine();
While(i>0, Write(i)); // ничего не выведет
object Range(int start, int stop, int step) 3 - Генерирует последовательность целых чисел в заданном диапазоне (не включая последнее значение). Возвращает экземпляр OverScript.LoopRange, который реализует IEnumerable.
foreach(int x in Range(10, 15)) Write(x+" "); //10 11 12 13 14
WriteLine();
foreach(int $x in Range(10, 20, 2)) Write(x+" "); //10 12 14 16 18
WriteLine();
foreach(int $x in Range(20, 10, -2)) Write(x+" "); //20 18 16 14 12
WriteLine();
foreach(int $x in Range(5)) Write(x+" "); //0 1 2 3 4
object FuncRef(function) - Возвращает ссылку на функцию (объект FuncReference, в котором хранится информация о функции и экземпляре класса). Функцию нужно указывать вместе с аргументами, которые могут быть любые (имеет значение только их тип), т.к. они будут использованы только при загрузке кода, для поиска нужной функции, принимающей соответствующие аргументы. Вызова функции в FuncRef не производится. object fn=FuncRef(Test(123));
WriteLine(Call(fn, 10)); //int x: 10
fn=FuncRef(Test(123L));
WriteLine(Call(fn, 555)); //long x: 555
fn=FuncRef(Test(ToByte(0)));
WriteLine(Call(fn, 9)); //byte x: 9
fn=FuncRef(Test(byte\)); //byte\ - это значение по умолчанию, т.е. 0 для чисел и null для ссылочных типов
WriteLine(Call(fn, 9)); //byte x: 9
fn=FuncRef(Test(""));
WriteLine(Call(fn, "HELLO")); //string x: HELLO
fn=FuncRef(Test());
WriteLine(Call(fn)); //Test!
fn=FuncRef(Test("", 0));
WriteLine(Call(fn, "OK", 777)); //OK; 777
ReadKey();
string Test(long x){return "long x: "+x;}
string Test(int x){return "int x: "+x;}
string Test(byte x){return "byte x: "+x;}
string Test(string x){return "string x: "+x;}
string Test(){return "Test!";}
string Test(string s, int x){return s+"; "+x;}
Если ссылка указывает на функцию в другом экземпляре, то этот экземпляр будет существовать, пока существует эта ссылка.
const object GC=typeof("System.GC");
Foo f=new Foo(5);
object fn = FuncRef(f.PrintX());
f=null; //ссылка на экземпляр Foo останется внутри fn, поэтому он не будет удалён
GC->Collect();
GC->WaitForPendingFinalizers();
Call(fn); //выведет 5 несмотря на то, что f==null
ReadKey();
class Foo{
public int X;
New(int x){X=x;}
public PrintX(){WriteLine(X);}
}
object FuncPureRef(function) - Возвращает ссылку на функцию без экземпляра, на котором её выполнять.Foo foo=new Foo(10);
Foo foo2=new Foo(20);
object fn=FuncPureRef((Foo\).Test(int\)); //берём ссылку без информации об объекте, на котором выполнять функцию. Foo\ - это Foo\null, т.е. экземпляр класса Foo. Вместо (Foo\).Test(int\) можно написать: new Foo().Test(int\). Сам объект типа Foo при этом создаваться не будет. (Foo\) или new Foo() просто указывают, что берётся экземплярная функция Test().
WriteLine(CallOn(fn, foo, 5)); //15 //Test() вызвана на foo
WriteLine(CallOn(fn, foo2, 5)); //25 //Test() вызвана на foo2
ReadKey();
class Foo{
public int X;
New(int x){
X=x;
}
public int Test(int v){
return X+v;
}
}
Функцию по ссылке можно выполнять на экземпляре любого класса. Вот пример, как получить значение приватной переменной экземпляра функцией, находящейся вне класса этого экземпляра:
Bar bar=new Bar(5); //создаём объект с X=5
object fn = FuncPureRef((Foo\).GetX()); //берём ссылку на экземплярную функцию GetX() класса Foo (без создания экземпляра Foo)
WriteLine(CallOn(fn, bar)); //5 // вызываем GetX() на объекте bar
ReadKey();
class Foo{
int X;
public int GetX(){ //этой функцией будет доставаться приватная переменная X из экземпляра Bar
return X;
}
}
class Bar{
int X; //это приватная (видна только внутри класса) переменная
New(int x){
X=x;
}
}
object DynCall(object obj, string funcName, params object[] args) - Динамически вызывает функцию. Помните, что аргументы должны соответствовать принимаемым функцией типам. В противном случае возможны ошибки.
Foo f=new Foo();
WriteLine(DynCall(f, "Test", "hello", 123)); //s=hello; x=123
ReadKey();
class Foo{
Test(string s, int x){WriteLine($"s={s}; x={x}");}
}
object EventHandler(func) 3 - Создаёт делегат EventHandler. Если задать аргумент типа, то будет создан EventHandler<TEventArgs>. object eh=EventHandler(OnEvent(null, null));
Raise(eh, "SomeSender", null); //sender: SomeSender; args=
Raise(eh, "SomeSender"); //sender: SomeSender; args=System.EventArgs
OnEvent(object sender, object args){
WriteLine($"sender: {sender}; args={args}");
}
object eh=EventHandler(OnEvent(object\, int[]\), int[]); //создание EventHandler<int[]>
Raise(eh, this, new int[]{10, 20, 30});
OnEvent(object sender, int[] arr){
WriteLine($"sender: {sender}"); //sender: Instance of App
WriteLine($"arr: "+Join(' ', arr)); //args: 10 20 30
}
object eh=EventHandler(OnEvent(null, null), "System.UInt64"); //создание EventHandler<ulong>
Raise(eh, this, As(5, "System.UInt64"));
ReadKey();
//вместо "System.UInt64" лучше писать typeof("System.UInt64"), или указывать константу:
//const object UInt64 = typeof("System.UInt64");
//object eh=EventHandler(FuncRef(OnEvent(null, null)), UInt64);
//Raise(eh, this, As(5, UInt64));
OnEvent(object sender, object v){ //v можно задать не object, а, например, long или byte, и работать будет (значение сконвертируется, либо возникнет исклюение).
WriteLine($"sender: {sender}; v={v}"); //sender: Instance of App; v=5
}
Из обычного объекта EventArgs получить данные можно через Reflection.
//Допустим, из dll на C# в событие передаётся объект типа:
//public class SomeEventArgs : EventArgs
//{
// public int X { get; set; }
//}
//Событие в вашем OverScript-коде, которое вызывается из внешней библиотеки:
OnEvent(object sender, object args){
object x=args->X; //тут через Reflection получаем значение свойства X
}
object Delegate(func, object type) 2 - Создаёт делегат указанного типа. Использует Delegate.CreateDelegate. object d=Delegate(OnUnhandledException(null, null), typeof("System.UnhandledExceptionEventHandler"));
WriteLine(d); //System.UnhandledExceptionEventHandler
ReadKey();
OnUnhandledException(object sender, object args){}
Можно создавать любые делегаты, но с количеством аргументов до 7.
object d=Delegate(Test(int\, long\), typeof("System.Func`3[System.Int32,System.Int64,System.String]")); //создание делегата обобщённого типа Func<int,long,string> (функция, принимающая int и long, а возвращающая string)
WriteLine(Raise(d, 2, 3L)); //x=2; y=3
string Test(int x, long y){
return $"x={x}; y={y}";
}
object DelegateByFuncRef(object funcRef, object type) 2 - Создаёт из ссылки на функцию делегат указанного типа. object fn=FuncRef(Test(int\, long\));
object d=DelegateByFuncRef(fn, typeof("System.Func`3[System.Int32,System.Int64,System.String]"));
string СallСhain(string separator) 2 - Возвращает строковое представление цепочки вызовов. separator - разделитель звеньев (по умолчанию "->").Test();
ReadKey();
Test(){
WriteLine(CallChain()); //App.Instance()->App.Test()
}
void Dispose(object obj) - Выполняет определяемые приложением задачи, связанные с удалением, высвобождением или сбросом неуправляемых ресурсов. Использует IDisposable.Dispose. object timer=LocalTimer(Write("Test "), 1000, true);
Sleep(3000);
Dispose(timer);
//Test Test Test End
ReadKey("End");
int GetHashCode(object obj) - Возвращает хэш-код для объекта. Использует Object.GetHashCode. WriteLine(GetHashCode("Test")); // 1228681308
bool Equals(object obj, object obj) - Определяет, равны ли два экземпляра объекта. Использует Object.Equals. WriteLine(Equals("Test", "Test")); //True
string AppInfo(string property) 2 - Возвращает значение, заданное директивой #app в первой строке. AppInfo() без аргументов возвращает массив всех данных в формате 'имя=значение'.#app HelloApp, Version="1.2.3.4", CustomParam=Test
WriteLine(AppInfo("Name")); // HelloApp // если Name не задано, то по умолчанию будет 'App'
WriteLine(AppInfo("Version")); // 1.2.3.4
WriteLine(AppInfo("CustomParam")); // Test
WriteLine("ALL: "+Join(", ", AppInfo())); // ALL: AppName: HelloApp, Version: 1.2.3.4, CustomParam: Test
string AppPath() - Возвращает путь к исполняемому скрипту (не к интерпретатору, а к папке с файлом вашего приложения).WriteLine(AppPath()); //D:\scripts\TestAppDir
string CurrentDirectory() - Возвращает полный путь к текущей рабочей папке. Использует Environment.CurrentDirectory.//Запускаем OverScript без аргументов командной строки
WriteLine(CommandLine()); //D:\Programs\OverScript\OverScript.dll
// Теперь запускаем OverScript из cmd с указанием файла скрипта и аргументов, которые передать в скрипт: >D:\Programs\OverScript\OverScript.exe D:\Scripts\TestApp.txt SomeArg1 SomeArg2
WriteLine(CommandLine()); //D:\Programs\OverScript\OverScript.dll D:\Scripts\TestApp.txt SomeArg1 SomeArg2
Определить, что скрипт был запущен из командной строки, можно проверив, есть ли в строке запуска пробел:
if(IndexOf(CommandLine(),' ')<0) WriteLine("Не из командной строки"); else WriteLine("Из командной строки");
Такой способ не сработает, если в пути к OverScript есть пробелы. В именах файлов и папок вместо пробелов рекомендуется всегда использовать подчёркивание (нижний пробел).StartProcess(@"C:\windows\system32\notepad.exe", @"D:\docs\test.txt", 3, false); // открывает на весь экран блокнот с указанным файлом
StartProcess(@"D:\docs\test.txt",,, false); // открывает файл в программе, которая по умолчанию используется для работы с txt-файлами
object proc=StartProcess(@"D:\docs\test.txt"); // открывает файл и ждёт его закрытия
WriteLine(proc); //InvalidOperationException: Process has exited, so the requested information is not available.
object proc=StartProcess(@"D:\docs\test.txt",,, false); // открывает файл и не ждёт его закрытия
WriteLine(proc); //"System.Diagnostics.Process (notepad)"
В StartProcess вместо fileName, arguments и windowStyle можно передавать объект ProcessStartInfo.object info=Create("System.Diagnostics.ProcessStartInfo, System" , "notepad", @"D:\docs\test.txt");
StartProcess(info, true);
string IniGet(string text, string option, string section) 2 - Возвращает из INI-текста значение настройки конфигурации в виде строки. Если настройка с заданным именем отсутствует, то возвращает null. INI может содержать отступы и комментарии, начинающиеся с ; и #. Строки могут быть как в кавычках с экранированием, так и без кавычек. car = BMW #марка
price = 12345,67 ;цена
color = White #цвет
string ini=ReadAllText("test.ini"); //читаем содержимое ini-файла, который лежит в папке с исполняющимся скриптом
WriteLine(IniGet(ini, "car")); //BMW
WriteLine(IniGet(ini, "price")); //12345,67
WriteLine(IniGet(ini, "color")); //White
Пример с секциями. Допустим, у нас есть ini-файл с двумя секциями (main и advanced):
//[main]
//car = BMW #марка
//color = Black #цвет
//[advanced]
//car = "BMW X3 20d xDrive III (G01)" #полное название
//color = Super Black #название цвета
string ini=ReadAllText("test.ini");
WriteLine(IniGet(ini, "car", "main")); //BMW
WriteLine(IniGet(ini, "car", "advanced")); //BMW X3 20d xDrive III (G01)
WriteLine(IniGet(ini, "color", "main")); //Black
WriteLine(IniGet(ini, "color", "advanced")); //Super Black
string IniSet(string text, string option, string section, object value) 2 - Добавляет или изменяет настройку в ini и возвращает новый ini-текст. Экранирует строки, если нужно. Если строка простая (не содержит символов, которые нужно экранировать), то она вставляется как есть. Нестроковые объекты преобразовываются в строки (через ToString(): true в True, 5.9 в 5,9; null в пустую строку). При изменении значений, отступы и комментарии сохраняются. Если нужной секции нет, то она добавляется.string ini="";
ini=IniSet(ini, "car", "Ford");
ini=IniSet(ini, "price", 56789.99m);
ini=IniSet(ini, "inStock", true);
ini=IniSet(ini, "website", "extended-info", null);
ini=IniSet(ini, "date", "extended-info", Now());
ini=IniSet(ini, "factory", "extended-info", @"""Ford River Rouge"" factory complex");
WriteLine(ini);
//car=Ford
//price=56789,99
//inStock=True
//
//[extended-info]
//website=
//date=02.08.2021 18:09:19
//factory="\"Ford River Rouge\" factory complex"
object Tuple(params object[] args) - Создаёт кортеж System.Tuple<> с неизменяемыми элементами.object t=Tuple(5, "test");
WriteLine(t->Item1); //5
WriteLine(t->Item2); //test
//t->Item2="hello"; //ошибка
object ValueTuple(params object[] args) - Создаёт кортеж System.ValueTuple<>. Это struct.object t=ValueTuple(5, "test");
WriteLine(t->Item1); //5
WriteLine(t->Item2); //test
t->Item2="hello";
WriteLine(t->Item2); //hello
object @(action0, action1, action2 ... , object resultArg) - Выполняет все аргументы и возвращает значение последнего. @ - это не имя функции, а указание, что нужно вызвать базовую функцию. Имя же функции пустое ("").int a, b;
WriteLine(@(a=2, b=3, a+b)); //5
@(Write("foo"), Write(" bar"), Write(" baz"), Write(" end")); //foo bar baz end
some _(some resultArg, action0, action1, action2 ...) - Выполняет все аргументы и возвращает значение первого. Возвращаемый тип - тип первого аргумента.WriteLine(_(555, Write("Hello "), Write("World "))); //Hello World 555
some __(some resultArg, action0, action1, action2 ...) - Выполняет все аргументы, начиная со второго, и возвращает значение первого (вычисляется последним). Возвращаемый тип - тип первого аргумента.int a, b;
WriteLine(__(a+b, a=2, b=a+1)); //5
object Enumerator(object instance) 3 - Создаёт объект-перечислитель, реализующий интерфейсы IEnumerator и IDisposable. Foo f=new Foo();
foreach(int item in f) Write(item+" "); //1 2 3 4 5
WriteLine();
ForEach(f, int $item, Write(item+" ")); //1 2 3 4 5 DISPOSE!
ReadKey();
class Foo{
object GetEnumerator(){
return Enumerator(new MyEnumerator()); //функция Enumerator делает из объекта перечислитель (IEnumerator)
//Можно из ссылок на функции создавать:
//MyEnumerator e=new MyEnumerator();
//object moveNext=FuncRef(e.MoveNext());
//object current=FuncRef(e.Current());
//object reset=FuncRef(e.Reset());
//object dispose=FuncRef(e.Dispose());
//return EnumeratorByFuncRefs(moveNext, current, reset, dispose); //dispose можно не задавать
}
}
class MyEnumerator{
int X;
public bool MoveNext(){ //вызывается при каждой итерации (включая первую) в foreach. Должен возвращать true, если перечисление не закончено (текущее значение не последнее), и false если перечисление вышло за пределы последнего элемента в коллекции (последовательности).
return(++X<=5 ? true : false);
}
public object Current(){ //возвращает значение текущей итерации
return X;
}
public Reset(){ //сбрасывает значение
X=0;
}
public Dispose(){ //срабатывает при очистке перечислителя (в OverScript foreach не вызывает Dispose, а функция ForEach вызывает)
WriteLine("DISPOSE!");
}
}
void Lock(object obj) 2 - Получает монопольную блокировку указанного объекта. Использует Monitor.Enter.object obj=new object();
bool lockTaken;
Lock(obj, lockTaken);
WriteLine(lockTaken); //True
Unlock(obj);
void SetBasePath(string path) - Задаёт базовый путь для относительных путей.SetBasePath(@"C:\files");
WriteLine(BasePath()); //C:\files
string str=ReadAllText("file.txt"); //чтение файла C:\files\file.txt
string CodeFile() - Возвращает путь файла, в котором находится эта функция.SetGlobal("x", 123);
int x=int\GetGlobal("x");
WriteLine(x); //123
void Throw(string exceptionName, string exceptionMessage) 3 - Выбрасывает исключение.
try{
@(WriteLine("Hello"), WriteLine("World"), Throw("TestException", "Some test exception")); //сначала выведется "Hello", потом "World", а потом выбросится исключение
}
catch{ //можно так перехватывать: catch$("TestException") или catch("OverScript.CustomThrownException"), чтобы перехватить все CustomThrownException
WriteLine(exName+"; "+exMessage); // TestException; Some test exception
WriteLine(GetType(exception)); //OverScript.CustomThrownException
Throw(); //работает так же, как и инструкция throw;
}
//TestException: Some test exception
ReadKey();
Если передавать имя и описание ошибки, то тип исключения всегда будет OverScript.CustomThrownException. В Throw можно передавать объекты Exception:
Throw(Create("System.ApplicationException", "Hello!"));
//ApplicationException: Hello!