Уютное сообщество C# разработчиков
2.52K subscribers
44 photos
53 links
Уютное сообщество C# - обучающий канал для разработчиков.

Полезные материалы по языку программирования.
Тесты на знание C#
Подсказки и трюки языка

@aldrson @viktorreh
加入频道
This media is not supported in your browser
VIEW IN TELEGRAM
Когда C# и Python разработчики пытаются что-то обсудить.
😁27🤨1
Где правильно создана переменная?
Anonymous Quiz
3%
x = 0;
1%
$x = 10;
72%
char symbol = 'A';
3%
int num = "1";
21%
float big_num = 23.2234;
👍6👎3
Главное противоречие ООП

Зачастую многие разработчики сталкиваются с популярным заблуждением в коммерческой разработке.

Оно заключается в том, что для каждого класса, который реализует какую-то логику должен быть свой интерфейс.

Эта ситуация называется InterfaceImplementationPair.

В самом деле привычка восходит корнями к C/C++, где принято разделять header и code файлы.

Однако, время ушло далеко вперёд и надобность в подобных действиях сегодня отсутствует.

Наличие интерфейсов в отсутствие полиморфного поведения, мокирования или потребности в поставке контракта наружу через библиотеку лишь увеличивает стоимость сопровождения кода и количество занимаемых байтов на диске хранилища кодовой базы.

Поэтому не стоит бояться отсутствия интерфейсов, код от этого не потеряет в чистоте.

#полезное #tips
👍42
Какая конструкция используется для выполнения повторяющихся действий?
Anonymous Quiz
2%
if
8%
switch
89%
for
2%
try
🤡32🤯5😁4
Как скрыть от потребителя библиотеки лишние зависимости?

Недавно, я написал небольшую надстройку над AutoFixture, которая позволяет при создании объекта базового абстрактного класса получить экземпляр случайного наследника.

Допустим, у нас есть подобная иерархия:

abstract class A { }
class B : A { }
class C : A { }

Если написать fixture.Create<A>(), то мы получим исключение, поскольку вызывать new для абстрактных классов запрещено.
Ожидается, что мы получим случайным образом либо new B(), либо new C().

Однако, базовый функционал библиотеки не даёт такого поведения из коробки.
С помощью моего NuGet пакета можно настроить fixture таким образом, и всё заработает:

fixture.CustomizePolymorphism<A>()
.WithDerivedType<B>()
.WithDerivedType<C>()
.BuildCustomization();

Так вот при создании библиотеки возникла проблема.
В связи с тем, что она создана как дополнение к AutoFixture, присутствует зависимость, которая потом попадает к потребителю в раздел Implicitly Installed Packages.
Согласитесь, неприятно.

Решается проблема очень просто, достаточно пометить зависимость атрибутом PrivateAssets со значением all в конфигурации файла проекта:

<PackageReference Include="AutoFixture" Version="4.18.0" PrivateAssets="all"/>

#полезное #tips
👍4🤔1
Что выведет код?
Anonymous Quiz
62%
a) HI hi
6%
b) 145 209
29%
c) HI 209
3%
d) 145 hi
🤯21👍11👎2
Что такое .NET?

.NET это фреймворк (платформа), написанный компанией Microsoft для создания множества разных типов приложений. Почему фреймворк назвали именно так, до сих пор до конца не ясно.

.NET позволяет работать со множеством языков - C#, F#, Visual Basic. C#, как вы поняли самый популярный.

На сегодняшний день, современным видением платформы то, что выросло из .NET Core. То есть, курс на кросс-платформенность и отсутствие привязки к операционной системе Windows. Тут уже и приложения быстрее, и можно собрать приложение из микросервисов в Docker контейнерах.

Что можно сделать с помощью .NET?
Веб, мобилки, десктоп, ML, геймдев, IoT и так далее.
Но люди все равно выберут Java, поэтому пожелаем роста платформе!

Если хотите узнать больше о платформе .NET, поделитесь этим в комментариях!

#полезное #tips
👍16🔥1
Freeze/Inject/Register в AutoFixture

Давным-давно, в первых версиях библиотеки балом правил Register. Два других метода ещё не существовали.

Определён он был следующим образом:

public static void Register<T>(this IFixture fixture, T item)

Однако, была и перегрузка:

public static void Register<T>(this IFixture fixture, Func<T> creator)

Какое-то время казалось, что это нормально, впрочем, вскоре пользователи стали путаться. Например, можно было написать следующий код:

fixture.Register(() => universe.LightUp());

Поскольку делегат может получаться путём приведения ссылкой на метод, то валидной была и следующая запись:

fixture.Register(universe.LightUp);

Что если universe.LightUp это обращение к свойству, а не к методу? Тогда была бы выбрана первая перегрузка.

Но это крайне неочевидно.
Поэтому первая перегрузка превратилась в Inject<T>(this IFixture fixture, T item).

У метода Freeze несколько другая история.
В прошлом оказалось, что достаточно часто встречается следующее использование AutoFixture в императивном стиле:

var foo = fixture.Create<Foo>();
fixture.Inject(foo);

Тогда, автор библиотеки решил, что это так называемая концепция заморозки.
В итоге два вызова превратились в один метод Freeze.

#полезное #tips
Какую самую главную ошибку совершают новички в ООП?

Начав изучать ООП, многие знакомятся с его тремя столпами: инкапсуляция, наследование и полиморфизм. Но удаётся ли правильно понять все из них?

Если выполнить поиск определения инкапсуляции в Google, то можно получить примерно следующее:

«Инкапсуляция в программировании — это принцип, согласно которому внутреннее устройство сущностей нужно объединять в специальной «оболочке» и скрывать от вмешательств извне.»

А теперь вспомним, что самыми популярными объектно-ориентированными языками программирования являются Java и C#, где модификаторы доступа (private, public, protected, etc.) это одни из самых используемых ключевых слов. И получается, что начинающие программисты путают сокрытие с инкапсуляцией.

На самом же деле, корректнее привести следующее определение:

«Инкапсуляция – это объединение в рамках одной структуры функций и данных, с которыми эти функции работают.»

То есть, в случае объектно-ориентированного программирования, создав некоторый объект, мы связали его данные с определёнными методами на всё время его жизни.

А в случае, например, обычных функций мы просто описали некий алгоритм, который описывает последовательность действий никак не связанных с некоторым состоянием.

Вот простой пример, чтобы понять разницу:

class Doubler
{
private readonly int value;

public Doubler(int value) => this.value = value;

public int Double() => this.value * 2;
}

//…

public int Double(int value) => value * 2;

#полезное #tips
16👍2
Многоликая регистрация в стандартном контейнере

Допустим, у нас есть некоторый класс, который реализует более одного интерфейса:

public interface IBar {}
public interface IFoo {}

public class FooBar : IFoo, IBar {}


Наша задача зарегистировать экземпляр FooBar таким образом, чтобы при внедрении зависимостей IBar и IFoo использовался один и тот же объект.

Попытавшись совершить регистрацию наивным путём, мы потерпим неудачу, зависимости будут ссылаться на разные экземпляры FooBar:

services.AddSingleton<IFoo, FooBar>();
services.AddSingleton<IBar, FooBar>();


Но проблема вполне решаема, достаточно лишь зарегистрировать вначале экземпляр FooBar и затем ссылаться на него:

services.AddSingleton<FooBar>();
services.AddSingleton<IFoo>(x => x.GetRequiredService<FooBar>());
services.AddSingleton<IBar>(x => x.GetRequiredService<FooBar>());

#полезное #tips
👍31
Пусть объявлен кортеж: var tuple = (5, 10). Как обратиться к значению 5?
Anonymous Quiz
30%
tuple[0]
56%
tuple.Item1
8%
tuple.first
5%
tuple.5
😁3