Привет, неизвестный путник!

Добро пожаловать в документацию по языку C#.NStar! Здесь вы найдете информацию о программах и программировании для чайников. Если вы не чайник и имеете хотя бы небольшой опыт программирования, можете сразу перейти к другим разделам.

Что такое программа?

Если вы читаете эту страницу, у вас наверняка есть браузер. Если вы играете в игры (а практически у всех, кто не программирует, компьютер в основном для игр), у них, кроме самой игры, часто есть установщик, программа запуска и т. д. Если у вас нет исключительных способностей к математике, вы, вероятно, пользуетесь калькулятором, причем, скорее всего, в середине 2020-х не имеете его как отдельный прибор, а пользуетесь калякулятором, встроенным в компьютер (ну или смартфон). И браузер, и установщик игры, и калькулятор, встроенный в компьютер - все это программы. (На самом деле игра - тоже программа.) Даже для установки C#.NStar нужно запустить программу, да и сам по себе C#.NStar - тоже программа. А программы пишутся на языках программирования. И пишут их совсем не боги, а обычные пользователи, такие, как вы. Да-да, вы тоже можете писать программы. Конечно же, написание программы - это не взмах палочкой, и вы не напишете свой Хром за несколько минут, для этого нужно учиться долгие годы, но если вы уже "загорелись" - поздравляем, ваша профессия выбрала вас!

Какие бывают программы?

В первом блоке мы уже упомянули несколько классов программ:
- Игры.
- Программы, решающие конкретную задачу или прикладные, такие как браузер и калькулятор.
- "Помощники" других программ или утилиты, такие как установщики и программы запуска.
- Программы для создания программ или языки программирования, такие как C#.NStar.
Но на самом деле список этим не исчерпывается:
- Браузер отображает веб-страницы, а многие веб-страницы сами по себе содержат программы - веб-программы или веб-приложения. "Приложение" - это почти то же самое, что и "программа", такой термин тоже очень часто употребляется программистами и не только ими. Пример веб-приложения - онлайн-тест или онлайн-опрос, чтобы отображать статистику, кто как проголосовал, или на сколько очков вы выполнили тест, нужна программа.
- Вы, возможно, игрались с наборами для раскрашивания или другого рисования, причем, возможно, не только карандашами или красками на бумаге, но и в компьютере. Это - графические редакторы, и чтобы по клику на картинку ее элементы менялись - это должна быть не просто картинка, а программа. Существуют также профессиональные графические редакторы, позволяющие создавать мультфильмы или графическую часть игр, но они не для чайников.
- Сама по себе Windows является программой, и относится к классу "Операционные системы" (ОС). У нее есть свои маленькие "помощники", обеспечивающие взаимодействие клавиатуры и мыши с монитором и динамиками - драйвера, которые тоже являются программами. К сожалению, драйвера вам не написать, так как они пишутся под конкретную ОС и конкретную модель конкретного устройства.
- Вы, возможно, так или иначе слышали о ChatGPT. Это искусственный интеллект - на момент написания этих строк вершина творения программистов со всего мира, самый сложный и самый функциональный класс программ.
Из всех этих классов C#.NStar подходит для большинства. Он однозначно не подходит для написания низкоуровневых программ в стиле ОС и драйверов, но это даже хорошо, так как на языках для ОС и драйверов не пишут ничего, кроме ОС и драйверов. C#.NStar в чистом виде не подходит для написания веб-приложений, чтобы веб-приложение, написанное на C#.NStar, работало, нужно писать вызывающую его утилиту на другом языке. C#.NStar, в принципе, подходит для написания игр, но если это гигантская игра с большим открытым бесшовным миром, как Lineedge, то написать ее будет намного сложнее, чем если использовать специальные инструменты, называемые "игровыми движками". Но если это что-то маленькое и простое, как три в ряд, то вы потратите больше времени на освоение движка, чем на написание такой игры на C#.NStar. (Ладно, открою страшную тайну, вот заготовка такой игры.) Для остальных классов же он подходит прекрасно. Но так получилось, что пока что язык находится на очень ранней стадии, и им нельзя пользоваться, только тестировать, но это у вас тоже прекрасно получится, так как если вы учитесь в начальной школе, то у вас наверняка богатое и, что еще важнее, не подавленное и не исковерканное стереотипами воображение.

Как устроена программа?

В разделе "Установка и запуск" мы упоминали, что программа по умолчанию на C#.NStar выводит строку "Hello, world!". Но как она это делает? Посмотрим на эту программу подробнее.
return - точка выхода или возврата из программы. На этом этапе можно представить программу, как огромный замок, с множеством комнат, предметов в них и действий, которые с этими предметами нужно выполнить. Вы, возможно, играли в игры, где нужно сбежать из такого замка. Если так, то вы помните, что там нужно находить предметы, а иногда и создавать их самому из более простых предметов, разнообразными способами применять их к элементам комнаты, и иногда в таких играх есть специальные узкие двери, через которые весь рюкзак не пронести, только один-два предмета, либо какие-то магические элементы, которые отнимают предметы. В программировании все то же самое, только вы сами создаете замок, и сами управляете тем, какие предметы "игрок" в эту игру - компьютер - через какую дверь сможет пронести, а какие нет. В настоящее время у нас предельно простой "замок" из одной комнаты и одного предмета в ней, и команда "return" позволяет выйти из этой комнаты.
"Hello, world!" - тот самый предмет, кусок текста. Все куски текста как предметы в C#.NStar заключаются в двойные кавычки, запомните это твердо! Если вы уберете кавычки, язык сообщит вам о множестве ошибок, но ни в одной из них ни слова не будет о том, что вы забыли кавычки. Возможно, когда-либо языки программирования научатся надежно отличать текст на предметах от инструкций, что делать с комнатами и предметами в них, и тогда, возможно, и кавычки будут не нужны или по желанию, но пока приходится об этом только мечтать. Поэтому обязательно берите куски текста, являющиеся предметами, а не инструкциями, в двойные кавычки!
Точка с запятой (;) - признак окончания конкретного действия, тоже обязательный компонент программы. Это не во всех языках именно точка с запятой, где-то другой символ, где-то просто одно действие в одной строке, но мы, разработчики C#.NStar, решили, что точка с запятой - самый удобный вариант.
Итак, наша программа указывает компьютеру, оказавшись в "замке" из одной комнаты, просто выйти из нее, взяв с собой кусок текста. Именно этот кусок текста мы и получаем в результате прохождения этой "игры" - на память, что мы когда-то "играли". Можно также выйти из "замка", ничего не взяв с собой - return null; (null пишется без кавычек и означает "ничего"), но мы поступим иначе - заставим компьютер сначала положить кусок текста в рюкзак (в ячейку компьютерной памяти), а затем выйти с этим рюкзаком:
var x = "Hello, world!";
return x;

Здесь мы создали переменную с именем x и значением "Hello, world!" - так это называют программисты. После чего вернулись с этой переменной из программы. У каждой ячейки "рюкзака" есть строго определенное назначение - ключ не войдет в ячейку для карандаша, а кусок текста - в ячейку для числа. Написав var, мы предложили компьютеру самому определить, в какую ячейку класть кусок текста, и как мы видим, он с этой задачей справился. Но мы можем и явно определить тип переменной:
string x = "Hello, world!";
return x;

Можно увидеть, что результат не изменился, потому что string - это и есть ячейка для куска текста. Но если в обеих программах заменить "Hello, world!" на 123 (без кавычек), то мы увидим разные результаты: в первом случае число так и вернется из программы без кавычек, а во втором - в кавычках, потому что в первом случае компьютер сам выбрал, в какую ячейку поместить число (а числа пишутся без кавычек), и сделал это правильно, а во втором мы явно указали ему поместить число в ячейку для куска текста, что допустимо, так как ячейка для куска текста "больше", чем ячейка для числа. А вот попытавшись выполнить обратное действие:
real x = "Hello, world!";
return x;

- вы получите сообщение об ошибке (во втором из нижних полей), так как кусок текста не помещается в ячейку для числа (real - это тип переменной, способный хранить только числа). По нашей команде компьютер может в любой момент "выкинуть" из переменной то, что там лежало, и положить что-то другое:
var x = "Hello";
x = "world!";
return x;

Получив вторую команду, компьютер выкинет текст "Hello" и поместит в ту же переменную текст "world!". Если мы напишем так:
var x = "Hello";
x = 123;
return x;

- мы получим число в кавычках, потому что компьютер сначала поместил в ячейку для текста "Hello", а затем в ту же ячейку - число 123! Вероятно, вы понимаете, почему тип переменной не может просто так взять и измениться.

Операторы

Пойдем дальше - заставим компьютер самостоятельно собирать предмет, с которым он выйдет из нашей пока что единственной "комнаты", из составных частей:
var x = "Hello";
return x + "world!";

Вероятно, вы ожидали увидеть нашу ставшую классикой строку. ("Строкой" программисты называют произвольный кусок текста, даже если по факту он состоит из тысяч строк или, наоборот, является лишь частью строки. Это особенности программистского сленга, и если вы хотите стать профессиональным программистом, вам придется к ним привыкать.) Но вы увидите кое-что другое - "Helloworld!"! Почему? А потому, что компьютер - не всемогущий маг, который может сотворить запятую и пробел из ничего. Мы еще вернемся к нетривиальным последствиям этого тривиального факта, а пока что нужно написать или так:
var x = "Hello, ";
return x + "world!";

- или так:
var x = "Hello";
return x + ", world!";

Лично мне, набирающему этот текст, первый вариант больше нравится. Вы можете выбрать свой, результат одинаковый. Но обязательно, соединяя строки, не забывать про знаки препинания и пробелы. Теперь сравните результаты этих двух программ:
var x = 123;
return x + 45;


var x = "123";
return x + "45";

Первая программа вернет 168, а вторая строку "12345"! Это пример того, что нужно правильно выбирать тип переменной, даже если вам кажется, что памяти у вас многие гигабайты и ее не жалко на несколько ячеек в вашей маленькой программе. Более того, если вы хотя бы одно из чисел заключите в кавычки, вы получите второй результат, так как число преобразуемо в строку, а наоборот нет. (На самом деле строка лишь неявно не преобразуема в число. Вы можете преобразовать принудительно или явно, но это сложно и не имеет смысла. Лучше сразу выбирайте нужный тип для переменной.)
Как вы думаете, что вернет каждая из следующих программ?
var x = 7;
return x * 2;


var x = "7";
return x * 2;


var x = 7;
return x * "2";


var x = "7";
return x * "2";

Вы получите три разных результата, а из двух программ, дающих одинаковый результат, одна выдаст предупреждение, а другая нет! И это не ошибка, а следствие выбора типа переменной.
Знаки "+" и "*" - это операторы, которые указывают компьютеру способ объединения двух значений. Можете попробовать также такие операторы: % pow << >> & | ^. Но есть и более интересные, например, "==". Если вы запустите такую программу:
var x = 7;
return x == 2;

- вы получите false! Что это такое? Это новый тип значений - логический (bool). Значений такого типа всего два: false и true. Это результат сравнения двух других значений. Те из вас, кто уже не в начальной, а в средней школе, изучают такое понятие, как "уравнение", так вот там левая и правая части сравниваются знаком "=", а в программировании - оператором "==", так как один знак "=" используется для другой цели - для присваивания переменной значения. Это лучше запомнить, так как язык иногда сообщает об этом, но не всегда. Есть и другие особенности - ">=", "<=" и "!=" вместо "⩾", "⩽" и "≠" соответственно, так как, согласитесь, было бы неудобно при каждой такой проверке лезть в таблицу символов. Эти сравнения чаще всего применяются в условиях, например:
var w = 100;
var h = 1.5;
var index = w / h / h;
if (index < 20)
    return "Дефицит веса";
else if (index <= 25)
    return "Нормальный вес";
else
    return "Избыток веса";

Такая программа также является классикой при обучении начинающих программистов. На ее примере хорошо видны основное условие - "if" - и действие, которое наступает, если основное условие не выполнено - "else" (я не уверен, проходят ли такое слово в начальной школе, так как сам учился много лет назад, у меня была другая школьная программа, но оно означает "иначе"). Меняя w и h, вы получите разные результаты, причем они не являются результатом простой арифметической или битовой (как операторы << или &) операции над этими двумя переменными! (К сожалению, в настоящее время C#.NStar не позволяет ввести эти переменные с использованием дополнительных полей, файлов или другого "внешнего" источника - прим. ред.) Обратите также внимание, что строка с условием не заканчивается точкой с запятой, и это важно, потому что иначе вы получите либо явную ошибку, как в данном случае, либо трудноуловимую ошибку в поведении программы, о которой язык вам не сообщит, и чтобы ее найти, нужно будет постараться (это называется логической ошибкой). Условие - одна из ключевых конструкций программирования, она есть в любом языке, от ассемблеров, на которых пишут ОС и драйвера, до редакторов уровней в некоторых играх. (Разве что в "кодах операций аналитической машины" ее не было - кто хочет, может поискать в Интернете, что это за язык.) Также перед действиями внутри условий ставятся отступы (это достигается клавишей Tab), это не обязательно, но очень рекомендуется, так как делает код красивее (так думает большинство программистов, вам тоже придется к этому привыкать).

Функции

Вероятно, вам уже не терпится узнать, как же создаются другие "комнаты" в нашем "замке". А делается это так:
real Function Double(real value)
{
    return value * 2;
}
return Double(5);

(Мы специально назвали переменную value, а не x, чтобы показать, что ее имя, в отличие от "чистой" математики, может быть не только однобуквенным.) Если из главной "комнаты" можно вернуться практически с чем угодно, то, создавая свою "комнату", вы сами решаете, с чем можно войти в нее и с чем вернуться! Делается это через заголовок функции, каким является первая строка ее объявления. Если вы поменяете real на string, вы получите функцию, которая возвращает удвоенную строку. Вы также можете передать в функцию и вернуть из нее значения разных типов:
string Function RealToString(real value)
{
    return "" + value;
}
return RealToString(123);

"" - это строка нулевой длины, такие тоже бывают! К слову, заголовок функции, так же как и заголовок условия и все другие заголовки, не заканчивается точкой с запятой. То же самое касается строк с фигурными скобками, так как это вообще не команды, а разделители между блоками команд. Вы также можете вызвать функцию несколько раз:
real Function Double(real value)
{
    return value * 2;
}
return Double(Double(Double(5)));

(Подумайте, почему такой трюк не сработает с функцией RealToString().) Вы даже можете создать цикл вызовов:
real Function Double(real value)
{
    return value * 2;
}
real x = 5;
repeat (7)
    x = Double(x);
return x;

Цикл - также важная конструкция, присутствующая в большинстве современных высокоуровневых языков программирования. А теперь попробуйте выполнить программу выше без явного указания типа x. Вы получите совсем другой результат, плюс предупреждение от языка! Почему? А потому, что хотя выше мы написали про "ячейки" для чисел и строк, и немного ниже - для логических значений, но на самом деле в C#.NStar множество типов чисел. Тип real - это действительное число, вы, вероятно, еще не учили такое в школе, но действительным может быть и положительное, и отрицательное число, как целое, так и дробное. И для учета всех этих возможностей компьютеру требуется больше ресурсов, чем, например, для целого неотрицательного числа минимальных размеров, каким является тип byte (вы можете видеть это слово в тексте предупреждения от языка). А по умолчанию при создании переменной компьютер старается экономить ресурсы. (И посмотреть "вперед себя", что будет происходить с этой переменной на следующих строках, он не может.) Тип byte может вместить число не больше 255 (вы, вероятно, знаете, что байт - это 8 бит, каждый из которых принимает всего два значения - 0 и 1 (или те самые false и true), так вот из двух бит можно составить четыре значения, из трех - восемь (можете проверить), а из восьми - 256, одним из которых является ноль, так что остается 255 натуральных чисел). Но вы можете и ресурсы компьютера сэкономить, и неправильного результата не получить! Для этого нужно объявить переменную, а также параметр функции и саму функцию, типом "int". Он занимает 4 байта (32 бита) и вмещает такой диапазон целых чисел, которого хватит для подавляющего большинства "практических" для вас целей (примерно по 2 миллиарда в плюс и в минус).
Язык также содержит множество встроенных функций, которые можно вызывать без объявления, например, Max(), Random(), IntToReal() (последняя с равным успехом преобразует и byte в real). Выше мы немного соврали про "замок" с единственной "комнатой", но надеемся, что вы понимаете оправданность этого для сохранения логики обучения. (Возможно, вам непонятно, как передать в функцию Max() несколько параметров, это делается через запятую, именно поэтому целая и дробная часть у числа типа real разделяются точкой, как в примере выше про вес.) К слову, если у числа типа real есть дробная часть, не будут корректно работать операции == и !=. Например:
var x = 0.1;
var y = 0.2;
var z = 0.3;
return x + y == z;

Вы получите false! И наоборот, поменяв == на != - true. Это потому, что хотя тип real большой и требует много ресурсов, но все равно не безграничный, а представление десятичной дроби (кроме узкой группы особых, таких как 0.5, 0.25 или 0.6875) одними лишь битами потребует бесконечного числа бит (примерно как представление дроби 5/11 десятичными цифрами), и поэтому все дробные числа (опять же, кроме вышеупомянутой особой группы) существуют в компьютере лишь в виде приближений (хотя в некоторых языках программирования есть специальные типы для дробей вида m/n, но они применяются лишь глубокими математиками и, как правило, для чисел, занимающих многие мегабайты, а не несколько байт). Более того, такой же фокус возможен и со строками:
var stringA = "конец";
var stringB = "света";
var stringC = "конец света";
return stringA + stringB == stringC;

И снова false! Но тут причина в другом, а именно в противоположном предыдущему: в нашем интеллекте строки существуют лишь в виде приближений их истинных значений! Мы привыкли считать строки "конец" и "конец " вполне одинаковыми, компьютер же прекрасно видит, что они не равны. Так, например, объединение слов "критическая" и "точка" не равно "критической точке", а объединение слов "Hello и "world" - словосочетанию "Hello, world". Это может показаться неправдоподобным, но, вероятно, даже великий и ужасный ChatGPT не разберет запрос, написанный без пробелов и знаков препинания. (Хотя мы не проверяли.) Поэтому крайне важно не забывать про пробелы и знаки препинания на границе строк при "склеивании".

Списки и кортежи

Выше мы писали, что можно передать в функцию несколько параметров, но можно также и вернуть несколько значений:
var value1 = 3.14159;
var value2 = "AAA";
var value3 = 5;
return (value1, value2, value3);

Вы угадали, имя переменной может содержать числа. Не может только начинаться с числа. Обратите внимание, что числа вернулись из нашей "главной комнаты" без кавычек! Мы создали кортеж из трех независимых значений! Это не сложение, не умножение, не склеивание. Это возврат трех независимых значений. Вот только, несмотря на появление запятых и пробелов, не думайте, что вы таким способом получите "Hello, world" из "Hello" и "world". Нет, вы получите две независимых строки: ("Hello", "world"). При попытке их склеить вы снова получите "Helloworld". Чтобы получить "Hello, world" из двух строк, только вставить запятую и пробел в одну из них, иначе никак. Вы спросите: а как же вернуть из вашей собственной функции несколько значений? А вот так:
(real, string, int) Function MakeTuple((real, string) value1, int value2)
{
    return (value1[1], value1[2], value2);
}
return MakeTuple((3.14159, "AAA"), 5);

Здесь мы не только возвращаем несколько значений из функции, но и делаем один из параметров вложенным кортежом, а также обращаемся к элементам этого вложенного кортежа. (Найдите, в каких местах это происходит.) Вы можете даже как передавать в функцию, так и возвращать из нее целые "деревья" вложенных кортежей:
(int, real)[3] Function SplitThreeNumbers((real, real, real) values)
{
    return ((Truncate(values[1]), Frac(values[1])), (Truncate(values[2]), Frac(values[2])), (Truncate(values[3]), Frac(values[3])));
}
return SplitThreeNumbers((2.71828, 3.14159, 365.2425));

Здесь функция возвращает сингулярный кортеж из трех одинаковых вложенных кортежей. На самом деле мы могли бы переписать и тип параметра функции как real[3] - это не изменило бы результат. Возможно, вам непонятно, что такое Truncate() и Frac(). Это встроенные функции, можете поиграться с ними самостоятельно. Возможно также, что вам непонятно, почему мы не создаем несколько своих функций в одной программе. Что же, давайте сделаем это:
real Function D(real[3] abc)
{
    return abc[2] * abc[2] - 4 * abc[1] * abc[3];
}
string Function DecomposeSquareTrinomial(real[3] abc)
{
    if (abc[1] == 0)
        return "Это не квадратный трехчлен";
    var d = D(abc);
    string first;
    if (abc[1] == 1)
        first = "";
    else if (abc[1] == -1)
        first = "-";
    else
        first = abc[1];
    if (d < 0)
        return "Неразложимо";
    else if (d == 0)
        return first + Format(abc[2] / (2 * abc[1])) + '²';
    else
    {
        var sqrtOfD = Sqrt(d);
        return first + Format((abc[2] + sqrtOfD) / (2 * abc[1])) + Format((abc[2] - sqrtOfD) / (2 * abc[1]));
    }
}
string Function Format(real n)
{
    if (n == 0)
        return "x";
    else if (n < 0)
        return "(x - " + (-n) + ")";
    else
        return "(x + " + n + ")";
}
return (DecomposeSquareTrinomial((3, 9, -30)), DecomposeSquareTrinomial((1, 16, 64)),
    DecomposeSquareTrinomial((-1, -1, -10)), DecomposeSquareTrinomial((0, 11, 5)),
    DecomposeSquareTrinomial((-1, 0, 0)), DecomposeSquareTrinomial((2, -11, 0)));

Если вы не понимаете, что делает функция DecomposeSquareTrinomial(), лучше даже не пытайтесь - это очень глубокая математика, мы тоже ее не до конца понимаем (шутка, разумеется😊, на самом деле вы тоже будете это проходить то ли в седьмом, то ли в восьмом классе). Главное для вас здесь - просто огромное количество незнакомых вам конструкций:
  1. Как мы уже написали, несколько функций. Причем вызвать функцию можно как из "верхней" для нее функции (как Format() из DecomposeSquareTrinomial()), так и из "нижней" (как D() из DecomposeSquareTrinomial()).
  2. Передача кортежа из функции в функцию как единого значения.
  3. Досрочный возврат из функции. В нашем случае, если первый элемент кортежа равен нулю, мы возвращаем "Это не квадратный трехчлен", после чего продолжаем выполнение функции. Но оно не продолжится. Выполнение функции заканчивается после оператора return!
  4. Объявление переменной без присвоения ей значения (string first;). В этом случае var недопустимо, если переменная объявляется без присвоения значения, тип необходимо указывать только явно! Также недопустимо упоминать переменную, которой не присвоено значение, в любых других выражениях, кроме этого самого присваивания. А вот после присваивания это уже можно делать, но только если присваивание было произведено и в if, и во всех else.
  5. Сложение строки с одним символом (символ - это любой элемент строки: буква, цифра, пробел, знак препинания или даже вообще невидимые символы, такие как перенос на новую строку). В отличие от строки, символ берется в одинарные кавычки.
  6. Несколько строк в условии. Они обязательно берутся в фигурные скобки, иначе в условии выполнится только первая, а остальные всегда. А если первая команда ядра условия - объявление переменной, то без фигурных скобок язык вообще выдаст ошибку - объявление переменной не может быть единственной командой ядра условия. Также можно и ядро цикла брать в фигурные скобки.
  7. Перенос одной команды на несколько строк. Это допустимо, а если команда длинная, даже рекомендуется. Именно поэтому "строка кода" и "команда" - не одно и то же. Также допустимо, но не рекомендуется, обратное - записывать несколько команд в одну строку, и для того, чтобы компьютер разделил их, как раз и нужна точка с запятой.
  8. Ну и по мелочи:
  9. Символ из таблицы символов. Строки в C#.NStar (не путать со строками кода!) поддерживают Юникод, который содержит алфавиты почти всех языков мира (кроме придуманных вами лично), все используемые не только вами и/или вашими близкими математические символы, такие как верхние индексы для степеней, и огромное количество других символов.
  10. Круглые скобки для изменения порядка действий. Так же, как в математике.
  11. C#.NStar регистрозависим. Для него имя функции D и имя переменной d - два разных понятия, он их не путает. При этом неправда, что язык различает, что то функция, а то переменная, одна вызывается, а другая считывается из памяти. Бывает, что функция тоже записывается в память и считывается оттуда, становясь одновременно и функцией, и переменной, как бы это ни было неправдоподобно. Но это уровень не начальной школы, а серьезного, профессионального программирования. Если вас это заинтересовало, учитесь программированию дальше, и вы обязательно дойдете до этого!

Ладно, хватит об этой запредельной для вас математике, мы еще забыли написать о списках. Это тоже коллекция значений, только произвольной длины. Зато в списке они не являются независимыми. Тип списка нужно всегда указывать явно, var не катит, иначе это будет не список, а кортеж:
list(3) int a = (((1, 2, 3), (4, 5, 6), (7, 8, 9)), ((10, 11, 12), (13, 14, 15), (16, 17, 18)), ((19, 20, 21), (22, 23, 24), (25, 26, 27)));
return a[1, 2, 3];

Здесь мы создали трехмерный список (в скобках после слова list указывается количество измерений), после чего обратились к нему по трем индексам. Число измерений никак не связано с количеством значений, а также не обязательно указывать все индексы:
list(4) int a = ((((1, 2), (3, 4)), ((5, 6), (7, 8))), (((9, 10), (11, 12)), ((13, 14), (15, 16))));
return a[2, 3];

(Подумайте без запуска, что вернет данная программа и вернет ли вообще что-либо и почему.) В принципе, в список можно даже добавлять значения уже после создания, а также удалять и вставлять в середину, но пока этот функционал не отлажен и работает плохо. При этом, в отличие от кортежа, каждое измерение списка может содержать не более 16 значений (кортеж - сколько сможете перечислить, пока не устанете):
list() int a = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27);
return a[20];

Этот код не работает, так как мы передали 27 значений в одном измерении, а можно только 16. (В n измерениях - можно 16n.)

Классы

Последняя конструкция C#.NStar, с которой вы познакомитесь на этом мини-курсе - классы. В продолжение аналогии выше с замком, можно представить, что этот замок строится не как средневековые замки, по одному кирпичику, а как современные панельные дома, из готовых блоков, так вот классы - это аналог как раз таких панельных блоков. Классы могут содержать множество "входов" в них - конструкторов, огромное количество "комнат" - функций - и практически безграничное пространство для воображения и творчества. Например:
Class MyClass
{
    int a = 5;
    real b = 3.14159;
    string c = "A";
 
    Constructor(bool bool)
    {
          if (bool)
          {
                 a = 12;
          }
    }
    real Function DoubledB()
    {
        return b * 2;
    }
}
MyClass a1 = new MyClass();
MyClass a2 = new MyClass(8, 2.71828, "$");
MyClass a3 = new MyClass(8, 2.71828);
MyClass a4 = new MyClass(true);
return (a1.a, a2.b, a3.DoubledB(), a4);

Здесь объявлен класс, содержащий три свойства (a, b, c), один конструктор (есть также встроенные конструкторы, автоматически добавляемые к любому классу) и один метод DoubledB() (метод - это функция, объявленная внутри класса, и пусть вас не смущает, что она без параметров - они ей не нужны, все необходимое она берет из своего класса) (хотя бывают и методы с параметрами). На этом наш мини-курс завершается. Надеемся, вам было интересно!



Назад к индексу документации