использовать условные конструкции для решения об отображении или неотображении тех или иных элементов GUI, либо иметь разные XAML-формы для разных групп пользователей
// [][] 4865 // [,] 5192 // [] 4852
IL_0000: ldarg 1 // кладёт в стек первый аргумент
IL_0001: ldarg 2 // кладёт в стек второй аргумент
IL_0002: sub // достаёт из стека два последних значения и отнимает последний от пред последнего (т.е. будет arg.2 - arg.1), результат складывается в стек
IL_0003: brtrue.s IL_0011 // достаёт из стека значение, если оно не 0, переходит к инструкции IL_0011, если 0 исполнения идёт дальше на I_0005
IL_0005: ldstr "zero" // загружает в стек строку "zero"
IL_000a: call void System.Console::WriteLine(string) // вызывает вывод в консоль, из стека достаются N нужных значений для параметров (в данном случае 1), void функция ничего в стек не добавляет
IL_000f: br.s IL_001b // переход (jump) к IL_001b
IL_0011: ldstr "not zero" // загружает в стек строку "not zero"
IL_0016: call void System.Console::WriteLine(string) // вызывает вывод в консоль, из стека достаётся 1 значения для параметра
IL_001b: ldstr "done" // загружает в стек строку ...
IL_0020: call void System.Console::WriteLine(string) // ...
#include <stdio.h>
enum Opcode {
OP_LOAD_ARGUMENT,
OP_LOAD_STRING,
OP_SUBTRACT,
OP_GOTO,
OP_GOTO_IF_TRUE,
OP_CALL,
OP_RETURN
};
union Argument {
int value;
const void* pointer;
};
struct Instruction {
Opcode opcode;
Argument arg;
};
void run_vm(const Instruction* instructions, const Argument* args) {
Argument stack[16];
Argument* stack_pointer = &stack[0];
int address = 0;
while(true) {
const Instruction instruction = instructions[address];
address++;
switch(instruction.opcode) {
case OP_RETURN:
return;
case OP_LOAD_ARGUMENT:
*stack_pointer = args[instruction.arg.value];
stack_pointer++;
break;
case OP_LOAD_STRING:
*stack_pointer = instruction.arg;
stack_pointer++;
break;
case OP_SUBTRACT:
{
stack_pointer--;
int b = stack_pointer->value;
stack_pointer--;
int a = stack_pointer->value;
stack_pointer->value = a - b;
stack_pointer++;
break;
}
case OP_GOTO:
address = instruction.arg.value;
break;
case OP_GOTO_IF_TRUE:
stack_pointer--;
if(stack_pointer->value != 0)
address = instruction.arg.value;
break;
case OP_CALL:
void (* fn)(const void*) = (void (*)(const void*))instruction.arg.pointer;
stack_pointer--;
fn(stack_pointer->pointer);
break;
}
}
}
void print(const char* text) { printf("%s\n", text); }
int main(int argc, char** argv) {
const Instruction instructions[] = {
/* 0 */ { OP_LOAD_ARGUMENT, { 0 } },
/* 1 */ { OP_LOAD_ARGUMENT, { 1 } },
/* 2 */ { OP_SUBTRACT, {} },
/* 3 */ { OP_GOTO_IF_TRUE, { 0x7 } },
/* 4 */ { OP_LOAD_STRING, { .pointer = "zero" } },
/* 5 */ { OP_CALL, { .pointer = (void*)&print } }, // функции надо где-то регистрировать, чтобы знать сколько у них параметров и какого они типа
/* 6 */ { OP_GOTO, { 0x9 } },
/* 7 */ { OP_LOAD_STRING, { .pointer = "not zero" } },
/* 8 */ { OP_CALL, { .pointer = (void*)&print } },
/* 9 */ { OP_LOAD_STRING, { .pointer = "done" } },
/* A */ { OP_CALL, { .pointer = (void*)&print } },
/* B */ { OP_RETURN, {} }
};
const Argument args[] = {
{ 100500 },
{ 777 }
};
run_vm(instructions, args);
return 0;
}
string n2string = "sdfihsdfguhdsfo[ghdfhgdsfhghdfsgdfhghdsfg9wh328932u82hbsab zb cx9832u83232hbnibcz";
int countMinus3 = n2string.Length - 3;
{
string lastThreeSymbols = n2string.Substring(countMinus3);
Console.WriteLine($"lastThreeSymbols = {lastThreeSymbols}");
}
{
string lastThreeSymbols = string.Concat(n2string.Where((_, i) => i >= countMinus3));
Console.WriteLine($"lastThreeSymbols = {lastThreeSymbols}");
}
{
string lastThreeSymbols = n2string.Where((_, i) => i >= countMinus3).Aggregate(string.Empty, (s, c) => s + c);
Console.WriteLine($"lastThreeSymbols = {lastThreeSymbols}");
}
{
string lastThreeSymbols = n2string.Aggregate(string.Empty, (s, c) => (s.Length > 2 ? s.Substring(1) : s) + c);
Console.WriteLine($"lastThreeSymbols = {lastThreeSymbols}");
}
var someItems = _someService.GetList();
foreach (var item in someItems) // item внутри не используется, можно убрать этот foreach
{
var additionalItems = _additionItemsSerivce.GetList();
foreach (var additionalItem in additionalItems)
{
var properties = additionalItem.Properties;
foreach (var property in properties)
{
property.First = true;
property.First = true; // зачем делать одно и тоже два раза?
_additionItemsSerivce.UpdateProperies(additionalItem); // property не используется, значит можно вынести за этот foreach
}
}
}
var additionalItems = _additionItemsSerivce.GetList();
foreach (var additionalItem in additionalItems)
{
var properties = additionalItem.Properties;
foreach (var property in properties)
property.First = true;
_additionItemsSerivce.UpdateProperies(additionalItem);
}
$"..."
- синтаксический сахар для get_node("...").private Node node;
public override void _Ready()
{
node = GetNode<Node>("../Node");
}
public static FileStream OpenRead(string path)
{
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
}
internal const FileShare DefaultShare = FileShare.Read;
public FileStream(string path, FileMode mode)
: this(path, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, DefaultShare, DefaultBufferSize, DefaultIsAsync) {}
ReadOnlySpan<byte>
можно распарсить число при помощи System.Buffers.Text.Utf8Parser.TryParse
var (a, b) = Console.ReadLine().Split(" ").Select(int.Parse);
public static class DeconstructEnumerable
{
public static void Deconstruct<T>(this System.Collections.Generic.IEnumerable<T> enumerable, out T item1, out T item2)
{
using var enumerator = enumerable.GetEnumerator();
if (!enumerator.MoveNext())
throw new ArgumentException("not enough values to unpack (expected 2, got 0)", nameof(enumerable));
item1 = enumerator.Current;
if (!enumerator.MoveNext())
throw new ArgumentException("not enough values to unpack (expected 2, got 1)", nameof(enumerable));
item2 = enumerator.Current;
if (enumerator.MoveNext())
throw new ArgumentException("too many values to unpack (expected 2)", nameof(enumerable));
}
}