Это характеристика языков программирования, при которой каждое выражение имеет строго определённый тип, и не допускаются неявные (автоматические) преобразования между типами, если они могут привести к ошибкам. В языках с строгой типизацией компилятор или интерпретатор проверяет типы данных на этапе компиляции или выполнения, чтобы предотвратить возможные ошибки.
Типы переменных и выражений известны и проверяются во время компиляции.
Автоматические преобразования между несовместимыми типами не допускаются. Например, строка не может быть неявно преобразована в целое число.
Если преобразование необходимо, программист должен явно указать это в коде, используя приведение типов.
Программа предотвращает операции, которые могут привести к ошибкам из-за несовместимости типов.
Примитивные типы
int number = 10;
string text = "Hello";
// Это вызовет ошибку компиляции, потому что `text` нельзя неявно преобразовать в `int`
// number = text;
// Необходимо явное преобразование
number = int.Parse("123"); // Явное преобразование строки в целое число
Классы и объекты
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person person = new Person();
person.Name = "John";
person.Age = 30;
// Это вызовет ошибку компиляции, так как типы не совместимы
// person.Age = "Thirty";
// Явное преобразование строки в целое число
person.Age = int.Parse("30");
Многие типичные ошибки могут быть обнаружены и исправлены еще до выполнения программы.
Явные типы и преобразования делают код более понятным.
Компилятор может более эффективно оптимизировать код, так как типы данных известны заранее.
Необходимость явных преобразований может увеличить объем кода.
Программисты могут столкнуться с ограничениями при работе с разнородными типами данных.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥3
Предназначены для проверки отдельных компонентов или модулей приложения в изоляции. Они помогают убедиться, что отдельные функции или методы работают правильно.
Цель: Проверка логики отдельных методов или классов.
Инструменты: xUnit, NUnit, MSTest.
using Xunit;
public class CalculatorTests
{
[Fact]
public void Add_SimpleValues_ReturnsSum()
{
var calculator = new Calculator();
var result = calculator.Add(2, 3);
Assert.Equal(5, result);
}
}
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
Проверяют взаимодействие между различными компонентами системы, убеждаясь, что они корректно работают вместе.
Цель: Проверка взаимодействия между модулями.
Инструменты: xUnit, NUnit, MSTest, плюс дополнительные библиотеки для тестирования баз данных или HTTP-запросов.
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;
public class IntegrationTests
{
private readonly HttpClient _client;
public IntegrationTests()
{
var appFactory = new CustomWebApplicationFactory<Startup>();
_client = appFactory.CreateClient();
}
[Fact]
public async Task Get_EndpointReturnsSuccessAndCorrectContentType()
{
var response = await _client.GetAsync("/api/values");
response.EnsureSuccessStatusCode();
Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType.ToString());
}
}
Проверяют, что приложение выполняет свои функции в соответствии с требованиями. Эти тесты проверяют конкретные сценарии использования.
Цель: Проверка функциональности приложения на уровне пользователя.
Инструменты: Selenium, Playwright, Cypress.
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Xunit;
public class UiTests
{
[Fact]
public void LoadPage_CheckTitle()
{
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl("https://example.com");
Assert.Equal("Example Domain", driver.Title);
}
}
}
Проверяют приложение в целом, включая взаимодействие с внешними системами и проверку всех требований.
Цель: Проверка всей системы в интегрированном виде.
Инструменты: JUnit, TestNG для Java, или те же инструменты, что и для функциональных тестов.
Проводятся для проверки, что приложение соответствует требованиям и готово к использованию клиентом или конечным пользователем.
Цель: Подтверждение соответствия приложения требованиям.
Инструменты: Cucumber, SpecFlow (для BDD).
Проверяют, что недавние изменения в коде не нарушили существующую функциональность.
Цель: Убедиться, что новые изменения не привели к новым багам.
Инструменты: Все инструменты для юнит-тестирования и функционального тестирования.
Проверяют, как приложение ведет себя под нагрузкой, например, при большом количестве одновременных пользователей или операций.
Цель: Оценка производительности и устойчивости приложения под нагрузкой.
Инструменты: JMeter, Gatling, Apache Bench.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥4
Используется для объявления небезопасного контекста кода, который позволяет выполнять низкоуровневые операции, такие как манипуляции с указателями. Эти операции обычно не разрешены в безопасном управляемом коде, но могут быть необходимы для взаимодействия с неуправляемым кодом, оптимизации производительности или доступа к определенным системным ресурсам.
Чтобы использовать указатели и выполнять небезопасные операции, нужно объявить метод, блок кода или тип как
unsafe. unsafe void UnsafeMethod()
{
int a = 10;
int* p = &a; // Использование указателя
Console.WriteLine(*p); // Разыменование указателя
}
Для компиляции кода с
unsafe необходимо включить поддержку небезопасного кода в настройках проекта. В Visual Studio это делается через свойства проекта:Указатели позволяют напрямую работать с адресами памяти, что может быть полезно для некоторых оптимизаций или взаимодействия с низкоуровневым кодом, написанным на C или C++.
unsafe void PointerExample()
{
int a = 5;
int* p = &a; // p указывает на адрес переменной a
Console.WriteLine((int)p); // Вывод адреса переменной a
Console.WriteLine(*p); // Вывод значения переменной a через указатель
}
Вы можете объявлять структуры с указателями и использовать их в небезопасном контексте.
unsafe struct UnsafeStruct
{
public int* Pointer;
}
stackalloc позволяет выделять память в стеке для массива в небезопасном контексте. Это может быть быстрее, чем выделение памяти в куче. unsafe void StackAllocExample()
{
int* array = stackalloc int[10]; // Выделение массива из 10 целых чисел в стеке
for (int i = 0; i < 10; i++)
{
array[i] = i;
}
}
Небезопасный код часто используется для взаимодействия с API, написанными на других языках, такими как C или C++.
[DllImport("user32.dll")]
extern static unsafe int MessageBox(IntPtr hWnd, char* text, char* caption, int options);
unsafe void CallUnmanagedCode()
{
char* text = "Hello, World!";
char* caption = "My Message Box";
MessageBox(IntPtr.Zero, text, caption, 0);
}Позволяет выполнять высокоэффективные операции с памятью.
Необходим для вызова функций из библиотек, написанных на других языках.
Предоставляет возможность прямого управления памятью и аппаратными ресурсами.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16
Может означать создание новой строки с измененным содержимым, поскольку строки являются неизменяемыми (immutable). Это означает, что после создания строковый объект не может быть изменен. Любые операции, которые, казалось бы, изменяют строку, на самом деле создают новую строку.
Вы можете изменить строку, объединяя её с другой строкой, используя оператор
+ или метод String.Concat. string original = "Hello";
string modified = original + " World";
Console.WriteLine(modified); // Output: "Hello World"
Метод
Replace позволяет заменить все вхождения указанной подстроки на другую подстроку. string original = "Hello, World!";
string modified = original.Replace("World", "C#");
Console.WriteLine(modified); // Output: "Hello, C#!"
Метод
Substring позволяет извлечь подстроку из строки. string original = "Hello, World!";
string modified = original.Substring(7, 5); // "World"
Console.WriteLine(modified); // Output: "World"
Метод
Insert вставляет подстроку в указанную позицию. string original = "Hello World";
string modified = original.Insert(5, ",");
Console.WriteLine(modified); // Output: "Hello, World"
Метод
Remove удаляет часть строки, начиная с указанного индекса. string original = "Hello, World!";
string modified = original.Remove(5, 7);
Console.WriteLine(modified); // Output: "Hello!"
Для частых изменений строк предпочтительнее использовать класс
StringBuilder, так как он более эффективен в плане производительности для операций, связанных с изменением строк. using System.Text;
StringBuilder sb = new StringBuilder("Hello");
sb.Append(", World");
sb.Replace("World", "C#");
string modified = sb.ToString();
Console.WriteLine(modified); // Output: "Hello, C#"
Предположим, у нас есть строка, и мы хотим выполнить несколько операций по её изменению: вставить подстроку, заменить часть строки и удалить часть строки.
string original = "The quick brown fox jumps over the lazy dog.";
// Вставка подстроки
string inserted = original.Insert(16, "red ");
// "The quick brown red fox jumps over the lazy dog."
// Замена подстроки
string replaced = inserted.Replace("red", "black");
// "The quick brown black fox jumps over the lazy dog."
// Удаление подстроки
string removed = replaced.Remove(40, 9);
// "The quick brown black fox jumps over the lazy."
Console.WriteLine(removed);
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥2
Представляют собой типы данных, которые хранят свои значения непосредственно. В отличие от ссылочных типов (reference types), которые хранят ссылки на объекты в памяти, значимые типы хранят данные непосредственно в переменной.
Значимые типы обычно хранятся в стеке, что делает их более эффективными по сравнению с ссылочными типами, которые хранятся в куче.
При присваивании одной переменной значимого типа другой переменной происходит копирование значения, а не ссылки.
Значимые типы не требуют работы сборщика мусора для освобождения памяти, так как они автоматически удаляются при выходе из области видимости.
Примитивные типы
int number = 10;
float temperature = 36.6f;
bool isAlive = true;
char letter = 'A';
Структуры
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
Point p1 = new Point(10, 20);
Point p2 = p1; // Копирование значения
p2.X = 30;
Console.WriteLine(p1.X); // Output: 10
Console.WriteLine(p2.X); // Output: 30
Перечисления
public enum DaysOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
DaysOfWeek today = DaysOfWeek.Monday;
Объекты ссылочных типов хранятся в куче, и на них ссылаются переменные.
При присваивании одной переменной ссылочного типа другой переменной копируется ссылка на объект, а не сам объект.
Сборщик мусора управляет памятью для объектов ссылочных типов, удаляя их, когда на них больше нет ссылок.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥4
Ссылочные типы хранятся в куче (heap), а переменные, которые их ссылаются, хранятся в стеке (stack).
Это область памяти, где выделяется память для объектов ссылочных типов. Куча управляется средой выполнения CLR (Common Language Runtime), и сборщик мусора (Garbage Collector) отвечает за освобождение памяти, когда объекты больше не используются.
Это область памяти, где хранятся значения переменных, которые ссылаются на объекты в куче, а также значения переменных значимых типов.
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
void Example()
{
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = person1; // person2 ссылается на тот же объект, что и person1
person2.Age = 35;
Console.WriteLine(person1.Age); // Output: 35
Console.WriteLine(person2.Age); // Output: 35
}
Когда выполняется
new Person { Name = "Alice", Age = 30 }, новый объект Person создается в куче. В памяти выделяется место для хранения полей Name и Age. Переменная person1 хранится в стеке и содержит ссылку на объект Person в куче.Переменная
person2 также хранится в стеке и получает копию ссылки, хранящейся в person1. Оба person1 и person2 теперь указывают на один и тот же объект в куче.Когда изменяется
person2.Age, на самом деле изменяется поле Age объекта Person, на который ссылаются обе переменные.Когда объект в куче больше не имеет активных ссылок из стека или других объектов, сборщик мусора может освободить память, занятую этим объектом. Это помогает управлять памятью и предотвращает утечки памяти.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1
Ключевые слова
ref и out используются для передачи аргументов по ссылке, что позволяет методам изменять значения переданных переменных. При этом сами ключевые слова не влияют на то, где выделяется память (в стеке или куче). Место выделения памяти определяется типом данных, который передается в метод.Передает переменную по ссылке, позволяя методу как читать, так и изменять значение переменной.
void Increment(ref int number)
{
number++;
}
int value = 5;
Increment(ref value);
Console.WriteLine(value); // Output: 6
Также передает переменную по ссылке, но требует, чтобы метод присвоил значение переменной перед тем, как метод завершится.
void Initialize(out int number)
{
number = 10;
}
int value;
Initialize(out value);
Console.WriteLine(value); // Output: 10
Переменные значимых типов, такие как
int, float, struct, хранятся в стеке. Когда такие переменные передаются в метод с ref или out, передается ссылка на место в стеке, где хранится значение. void ProcessValue(ref int value)
{
value = 42; // Изменение значения переменной в стеке
}
int x = 10;
ProcessValue(ref x); // Передача ссылки на переменную x в стеке
Переменные ссылочных типов, такие как объекты классов, хранятся в куче, а ссылки на эти объекты — в стеке. При передаче ссылочных типов с
ref или out, передается сама ссылка на объект в куче. void UpdatePerson(ref Person person)
{
person.Name = "Updated Name"; // Изменение объекта в куче
}
Person person = new Person { Name = "Original Name" };
UpdatePerson(ref person); // Передача ссылки на объект person
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥5
Представляют собой мощный инструмент для работы с кодом на уровне его синтаксического дерева. Они позволяют программно строить, анализировать и выполнять выражения, представленные в виде дерева объектов.
Деревья выражений — это структура данных, которая представляет собой синтаксическое дерево выражения. Они позволяют рассматривать и манипулировать кодом как данными.
Деревья выражений находятся в пространстве имен
System.Linq.Expressions.Позволяют создавать и компилировать код во время выполнения.
Полезны для инструментов анализа кода, таких как ORM (например, Entity Framework), которые преобразуют выражения LINQ в SQL-запросы.
Помогают в сценариях, где нужно исследовать и манипулировать кодом на уровне метаданных.
Простое арифметическое выражение
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
// Создаем параметры для выражения
ParameterExpression paramA = Expression.Parameter(typeof(int), "a");
ParameterExpression paramB = Expression.Parameter(typeof(int), "b");
// Создаем выражение: a + b
BinaryExpression body = Expression.Add(paramA, paramB);
// Компилируем выражение в делегат
var add = Expression.Lambda<Func<int, int, int>>(body, paramA, paramB).Compile();
// Используем делегат
int result = add(2, 3);
Console.WriteLine(result); // Output: 5
}
}
Выражение с логикой
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
// Создаем параметры для выражения
ParameterExpression paramX = Expression.Parameter(typeof(int), "x");
ParameterExpression paramY = Expression.Parameter(typeof(int), "y");
// Создаем выражение: x > y ? x - y : y - x
Expression condition = Expression.Condition(
Expression.GreaterThan(paramX, paramY),
Expression.Subtract(paramX, paramY),
Expression.Subtract(paramY, paramX)
);
// Компилируем выражение в делегат
var compareAndSubtract = Expression.Lambda<Func<int, int, int>>(condition, paramX, paramY).Compile();
// Используем делегат
int result1 = compareAndSubtract(10, 5); // Output: 5
int result2 = compareAndSubtract(3, 8); // Output: 5
Console.WriteLine(result1);
Console.WriteLine(result2);
}
}
Одним из наиболее распространенных примеров использования деревьев выражений является LINQ. Когда вы пишете выражения LINQ, такие как
Queryable.Where, они часто переводятся в деревья выражений, которые затем могут быть преобразованы в SQL-запросы или другие форматы. using System;
using System.Linq;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Func<int, bool>> expr = x => x > 5;
// Разбор дерева выражений
var body = (BinaryExpression)expr.Body;
var left = (ParameterExpression)body.Left;
var right = (ConstantExpression)body.Right;
Console.WriteLine($"Left: {left.Name}, Right: {right.Value}"); // Output: Left: x, Right: 5
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
Для представления кода в виде структур данных, что позволяет программно создавать, анализировать и выполнять этот код. Это дает мощные возможности для динамической работы с кодом, включая создание, трансформацию и выполнение выражений во время выполнения программы.
Expression`ы широко используются в ORM (Object-Relational Mapping) системах, таких как Entity Framework и LINQ to SQL, для преобразования выражений LINQ в SQL-запросы.
using (var context = new MyDbContext())
{
var query = context.Users.Where(u => u.Age > 30);
// Выражение `u => u.Age > 30` представлено как Expression и переводится в SQL
foreach (var user in query)
{
Console.WriteLine(user.Name);
}
}
Expression`ы позволяют создавать динамические запросы, которые могут изменяться в зависимости от условий во время выполнения программы.
public static IQueryable<T> ApplyFilter<T>(IQueryable<T> query, string propertyName, object value)
{
var parameter = Expression.Parameter(typeof(T), "x");
var member = Expression.Property(parameter, propertyName);
var constant = Expression.Constant(value);
var body = Expression.Equal(member, constant);
var predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
return query.Where(predicate);
}
Expression`ы можно использовать для создания делегатов, которые компилируются во время выполнения, что позволяет динамически генерировать и выполнять код.
Expression<Func<int, int, int>> expr = (a, b) => a + b;
var func = expr.Compile();
int result = func(2, 3); // result = 5
Expression`ы позволяют анализировать и изменять выражения, что полезно для создания библиотек и фреймворков, которые работают с выражениями.
Expression<Func<int, bool>> expr = x => x > 5;
var body = (BinaryExpression)expr.Body;
var left = (ParameterExpression)body.Left;
var right = (ConstantExpression)body.Right;
Console.WriteLine($"Left: {left.Name}, Right: {right.Value}"); // Output: Left: x, Right: 5
Expression`ы могут быть использованы для создания динамических правил валидации и их проверки.
public static Func<T, bool> GetValidator<T>(string propertyName, object value)
{
var parameter = Expression.Parameter(typeof(T), "x");
var member = Expression.Property(parameter, propertyName);
var constant = Expression.Constant(value);
var body = Expression.Equal(member, constant);
return Expression.Lambda<Func<T, bool>>(body, parameter).Compile();
}
var validateAge = GetValidator<User>("Age", 30);
bool isValid = validateAge(new User { Age = 30 }); // isValid = true
Expression`ы могут быть использованы для создания кэша выражений, что позволяет оптимизировать выполнение часто повторяющихся операций.
var parameter = Expression.Parameter(typeof(int), "x");
var body = Expression.Multiply(parameter, Expression.Constant(2));
var lambda = Expression.Lambda<Func<int, int>>(body, parameter);
var compiled = lambda.Compile();
// Кэшируем делегат
var cache = new Dictionary<int, Func<int, int>>();
cache[2] = compiled;
int result = cache ; // result = 6
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍2
1. Централизованное управление: Сервис локатор держит реестр всех доступных сервисов и предоставляет их по запросу, что упрощает управление жизненным циклом объектов.
2. Гибкость: Шаблон позволяет легко заменять и обновлять сервисы без изменения кода, который их использует, что делает приложение более модульным.
3. Изоляция зависимостей: С помощью сервис локатора, компоненты могут запрашивать зависимости в рантайме, что снижает зависимость от конкретных реализаций.
Однако стоит учитывать, что чрезмерное использование сервис локатора может привести к скрытому управлению зависимостями, что усложняет отслеживание и управление ими в больших приложениях. Это может сделать архитектуру приложения менее прозрачной и затруднить отладку и тестирование.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍3❤1
Forwarded from Идущий к IT
Твое резюме на HeadHunter — ОК, если ты видишь это.
HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.
Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.
Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.
Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.
О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео
HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.
Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.
Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.
Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.
О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео
😁2👍1
Это структура данных, представляющая код в виде дерева. Деревья выражений позволяют программно строить, анализировать и выполнять код. Это мощный инструмент для динамического создания и трансформации выражений, что делает их полезными в различных сценариях, таких как LINQ, ORM (например, Entity Framework), динамическое построение запросов и создание компилируемых делегатов.
Это структура данных, которая представляет синтаксическое дерево кода. Каждая нода (узел) дерева является экземпляром класса
Expression или его производных.Пространство имен, в котором находятся классы и методы для работы с деревьями выражений.
Простое арифметическое выражение
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
// Создаем параметры для выражения
ParameterExpression paramA = Expression.Parameter(typeof(int), "a");
ParameterExpression paramB = Expression.Parameter(typeof(int), "b");
// Создаем выражение: a + b
BinaryExpression body = Expression.Add(paramA, paramB);
// Компилируем выражение в делегат
var add = Expression.Lambda<Func<int, int, int>>(body, paramA, paramB).Compile();
// Используем делегат
int result = add(2, 3);
Console.WriteLine(result); // Output: 5
}
}
Деревья выражений широко используются в ORM системах для преобразования выражений LINQ в SQL-запросы. Это позволяет использовать LINQ-запросы для взаимодействия с базами данных.
using (var context = new MyDbContext())
{
var query = context.Users.Where(u => u.Age > 30);
// Выражение `u => u.Age > 30` представлено как Expression и переводится в SQL
foreach (var user in query)
{
Console.WriteLine(user.Name);
}
}
Деревья выражений позволяют создавать динамические запросы, которые могут изменяться в зависимости от условий во время выполнения программы.
public static IQueryable<T> ApplyFilter<T>(IQueryable<T> query, string propertyName, object value)
{
var parameter = Expression.Parameter(typeof(T), "x");
var member = Expression.Property(parameter, propertyName);
var constant = Expression.Constant(value);
var body = Expression.Equal(member, constant);
var predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
return query.Where(predicate);
}
Деревья выражений можно использовать для создания делегатов, которые компилируются во время выполнения, что позволяет динамически генерировать и выполнять код.
Expression<Func<int, int, int>> expr = (a, b) => a + b;
var func = expr.Compile();
int result = func(2, 3); // result = 5
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4