Все самое полезное для C#-разработчика в одном канале.
Наши курсы: https://clc.to/y3LDtw
По рекламе: @tproger_sales_bot
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Post #6757
3.66K
БИ @csharpproglib
Showing posts older than #6758 · Back to latest

LangGraph);
Что такое абстракция в ООП?

cat заметка.md | md2cb
# Ctrl+V в любое приложение
md2cb -e # открывает $EDITOR, конвертирует после сохранения

IChatClient client = ...; // любой провайдер
await foreach (var update in client.GetStreamingResponseAsync("How are you?"))
{
Console.Write(update);
}
record Family(List<Person> Parents, List<Person>? Children);
record Person(string Name, int Age);
var family = await client.GetResponseAsync<Family>(
[
new ChatMessage(ChatRole.System, "You are an AI assistant..."),
new ChatMessage(ChatRole.User, "Create a family with 2 parents...")
]);
var image = new DataContent(File.ReadAllBytes(@"photo.jpg"), "image/jpeg");
var messages = new List<ChatMessage>
{
new(ChatRole.System, "You are a photo analyst..."),
new(ChatRole.User, [prompt, image])
};
record ImageAnalysis(string Description, string[] Tags);
var analysis = await client.GetResponseAsync<ImageAnalysis>(messages);
// Универсальная функция-монстр
public async Task<object> FetchDataAsync(
string entityType, int? id, string filter,
int pageSize, bool includeDeleted, params string[] includes) { }
// Специализированные методы
public async Task<List<User>> GetActiveUsersAsync(int page, int pageSize)
=> await _context.Users.Where(u => u.IsActive)
.Skip(page * pageSize).Take(pageSize).ToListAsync();
// Кажется умным, но бесполезен
public interface IRepository<T> where T : class
{
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
}
// Специфичный и полезный
public interface IUserRepository
{
Task<User> GetByEmailAsync(string email);
Task<User> GetWithOrdersAsync(int id);
}
// НЕ объединяйте! Разные бизнес-концепции
public string FormatUserName(User u) => $"{u.FirstName} {u.LastName}";
public string FormatProductName(Product p) => $"{p.Brand} {p.Model}";
// UI: простая проверка
public bool ValidateEmail(string email) => email.Contains("@");
// API: строгая проверка
public bool ValidateEmail(string email) =>
Regex.IsMatch(email, @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
[Fact]
public void CreateUser_ShouldSucceed()
{
var user = new User { Name = "Alice", Age = 25 };
Assert.Equal("Alice", _service.CreateUser(user).Name);
}
[Fact]
public void UpdateUser_ShouldSucceed()
{
var user = new User { Name = "Alice", Age = 25 }; // OK
// Читаемость важнее DRY
}


int result = 10 * 5 + 3 * 2, компилятор прекрасно понимает, что результат всегда будет 56, и именно это число окажется в скомпилированном коде.public void Example()
{
int result = 10 * 5 + 3 * 2; // Вы пишете это
// Компилятор превращает в:
int result = 56; // Уже посчитано
}
public void ConstantPropagation()
{
const int multiplier = 100;
int value = 42;
int calculated = value * multiplier;
// Компилятор оптимизирует до:
int calculated = value * 100; // multiplier заменен значением
}
string message = "Hello" + " " + "World"; превращается в string message = "Hello World";public void StringOptimization()
{
// Все литералы склеиваются в один
string message = "Hello" + " " + "World";
// Результат: string message = "Hello World";
// С константами тоже работает частично
const string greeting = "Hello";
string name = "Alice";
string message = greeting + " " + name;
// Результат: string message = "Hello " + name;
}
const там, где это уместно, не бойтесь записывать формулы явно вместо магических чисел – компилятор сам посчитает результат.
git maintenance is-needed — проверка, нужно ли выполнять задачи обслуживания репозитория.git repo info --all — показывает расширенную информацию о структуре репозитория.git blame --diff-algorithm=<algo> — теперь можно выбрать алгоритм сравнения при отслеживании изменений.git replay — теперь выполняет обновление ссылок самостоятельно, не требуя дополнительных команд.git fast-import — новая опция --signed-commits=strip-if-invalid для удаления невалидных подписей.git apply и git diff — новый класс ошибок пробелов incomplete-line.namespace MyCompany.PaymentSystem
{
public class PaymentProcessor
{
// ...
}
}
namespace MyCompany.Logging
{
public class Logger
{
// ...
}
}
MyApp.Logger и ThirdPartyLib.Logger одновременно.MyCompany.Ecommerce.Orders, MyCompany.Ecommerce.Products, MyCompany.Ecommerce.Payments.using MyCompany.Ecommerce.Orders;
var order = new Order(); // Вместо: new MyCompany.Ecommerce.Orders.Order()
// GlobalUsings.cs
global using System;
global using MyCompany.Core;
.exe — приложение, которое можно запустить..dll — библиотека для подключения.<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
using Newtonsoft.Json; // Импортируем namespace
var json = JsonConvert.SerializeObject(obj);
//или без using
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
public int Calculate(int a, int b)
{
return Add(a, b) * 2;
}
private int Add(int a, int b) // JIT заинлайнит автоматически
{
return a + b;
}
public int Calculate(int a, int b)
{
return (a + b) * 2; // тело Add() вставлено напрямую
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int Multiply(int a, int b)
{
return a * b;
}

Semantic Kernel, но глобальный стандарт задаёт LangGraph. Его киллер-фича — явное управление графом выполнения и состоянием (Stateful Graph).
Random в .NET генерирует псевдослучайные числа для игр, тестов или симуляций. Он работает на основе сида, обычно времени, и дает целые, дробные значения или байты.System.Random создает последовательности чисел через алгоритм. Для простого инта берут Next(min, max), где верхняя граница не включается.var rng = new Random();
int число = rng.Next(1, 101); // от 1 до 100
NextDouble возвращает от 0.0 до 1.0, умножьте и сдвиньте для нужного интервала. Байты через NextBytes заполняют массив. Это для тестовых файлов или симуляций.double температура = rng.NextDouble() * 50 - 10; // от -10 до 40
byte[] буфер = new byte[16];
rng.NextBytes(буфер);
Random не годится для токенов или паролей, предсказуем при известном сиде. Берите RandomNumberGenerator из System.Security.Cryptography для криптографии.GetInt32(1, 101) или Fill для байт. В API для ключей всегда крипто-вариант.Random не потокобезопасен, общий экземпляр сломается. ThreadLocal<Random> создаст по инстансу на поток. Parallel.For с ним работает корректно, без гонок:var локальныйRng = new ThreadLocal<Random>(() => new Random());
Parallel.For(0, 100, i => {
int значение = локальныйRng.Value!.Next(100);
});

public class User
{
public string Name { get; set; }
public static bool operator true(User? user) => user?.Name != null;
public static bool operator false(User? user) => user?.Name == null;
}
if (user) сработает если имя задано, иначе попадет в else. Компилятор автоматически вызывает нужный оператор при булевом контексте.is not null или !ReferenceEquals(null, obj).