• Почему приложение вылетает после перехода на третье Activity?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Вообще переход на новую Activity делается по-другому. Почитай книгу Android. Программирование для профессионалов, много вопросов отпадут. Только обзаведись английской версией, чтобы смотреть в неё, когда не понятно, что имеется ввиду под некоторыми словами. И подписку на клики в XML лучше не делать. Методы именуются с маленькой буквы (camelCase).

    Инструкция, как ловить исключения
    Выполни по инструкции ниже всё и потом ты сможешь смотреть, какое произошло исключение, если приложение будет крашиться. Просто ставь точку останова на строке println(message) и когда сработает обработчик не перехваченного исключения, то там ты и посмотришь, что в нём написано.

    Создай класс TestAppUncaughtExceptionHandler
    package com.example.test
    
    import java.lang.Thread.UncaughtExceptionHandler
    
    class TestAppUncaughtExceptionHandler : UncaughtExceptionHandler {
    	override fun uncaughtException(thread: Thread, ex: Throwable) {
    		val message = "Thread name: ${thread.name}, Exception: ${ex.fillInStackTrace()}"
    		// На строке ниже ставь точку останова (breakpoint) и смотри, что написано в исключении.
    		println(message) 
    	}
    }


    Создай класс TestApplication
    package com.example.test
    
    import android.app.Application
    
    // Указывается в манифесте, чтобы работал
    class TestApplication : Application() {
    	override fun onCreate() {
    		super.onCreate()
    		
    		Thread.setDefaultUncaughtExceptionHandler(TestAppUncaughtExceptionHandler())
    	}
    }


    В AndroidManifest.xml файл добавь android:name=".TestApplication"

    Пример AndroidManifest.xml (многое удалено для краткости)
    <?xml version="1.0" encoding="utf-8"?>
    <manifest package="com.example.test"
    	xmlns:android="http://schemas.android.com/apk/res/android">
    
    	<application
    		android:name=".TestApplication">
    		<activity
                       ...
    		</activity>
    	</application>
    
    </manifest>
    Ответ написан
    1 комментарий
  • Как узнать айпи адрес сайта в С#?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Порты:
    1. 80 – http
    2. 443 – https


    Программа
    using System.Net;
    
    namespace ConsoleApp;
    
    internal class Program
    {
        private const int SUCCESS = 0;
        private const int COMMAND_LINE_ARGS_ARE_NOT_SPECIFIED = 1;
        private const int EXCEPTION_THROWN = 2;
    
        private static Task<int> Main(string[] args)
        {
            return new Program().Run(args);
        }
    
        private async Task<int> Run(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Not enough positional command-line arguments specified!");
                return COMMAND_LINE_ARGS_ARE_NOT_SPECIFIED;
            }
    
            try
            {
                foreach (string hostName in args)
                {
                    IPHostEntry hostEntry = await Dns.GetHostEntryAsync(hostName);
                    DisplayHost(hostEntry);
                }
    
                return SUCCESS;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return EXCEPTION_THROWN;
            }
        }
    
        private void DisplayHost(IPHostEntry hostEntry)
        {
            Console.WriteLine(hostEntry.HostName);
            foreach (var ipAddress in hostEntry.AddressList)
            {
                Console.WriteLine(ipAddress);
            }
            Console.WriteLine("---");
        }
    }


    ConsoleApp.csproj
    <Project Sdk="Microsoft.NET.Sdk">
    
        <PropertyGroup>
            <OutputType>Exe</OutputType>
            <TargetFramework>net6.0</TargetFramework>
            <ImplicitUsings>enable</ImplicitUsings>
            <Nullable>enable</Nullable>
        </PropertyGroup>
    
    </Project>
    Ответ написан
    2 комментария
  • Как преобразовать время в миллисекунды в kotlin?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    import java.time.LocalTime
    import java.time.format.DateTimeFormatter
    
    // ---
    val formatter = DateTimeFormatter.ISO_LOCAL_TIME
    val time = LocalTime.parse("16:07:08.900700901", formatter)
    println(time.nano)
    Ответ написан
  • Xamarin — есть ли книги на русском?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Usmanakk, в дополнение к предложенной выше книге по Xamarin:
    Android. Программирование для профессионалов. 4-е издание | Гарднер Брайан, Марсикано Кристин

    Книги в первую очередь ищи на Amazon (на английском). Потом уже их перевод.

    Если знаешь C#, то Kotlin во-первых, покажется даже красивее и удобнее, чем C#, во-вторых там ничего в нём нет такого, что бы нужно было прям изучать месяцами. Я за пару дней понял, что к чему и уже по этой книге нормально писал примеры (на самом деле я сразу писал их, но по мелочи то там, то там разбирался с Kotlin). Чтобы понимать, что там к чему, в Android Studio можно посмотреть байт-код Kotlin и декомпилировать его в Java. A Java 1 в 1 C# (грубо говоря, разница конечно есть и не только в синтаксисе). Открываешь файл с Kotlin кодом, дальше Tools - Kotlin - Show Kotlin Bytecode. В открывшемся окне кнопка Decompile. Android Studio удобно ставить и обновлять через JetBrains Toolbox

    Всё сделаешь по книге, скорее всего, Xamarin и не понадобится, а если понадобится, то будет легко потому что ты знаешь как писать нативно приложения под Android. Да, сейчас уже зарелизили MAUI.

    https://ttu.github.io/kotlin-is-like-csharp/ (сравнение как сделать на Kotlin и то же самое на C#)
    https://developer.android.com/docs
    Ответ написан
    Комментировать
  • Какая книга лучше?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Можно смело начинать учить по книге с C# 9
    Скорее всего, это все отличия (см. по ссылкам). В книге по 9 версии не будет информации о версиях 10 и 11
    Новые возможности C# 10
    Новые возможности C# 11
    Ответ написан
    Комментировать
  • Как можно исправить код для поиска квадратных уравнений?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    using static ConsoleApp.ConsoleInput;
    
    namespace ConsoleApp;
    
    public class Program
    {
        static void Main(string[] args)
        {
            new Program().Run(args);
        }
    
        private void Run(string[] args)
        {
            Console.WriteLine("Введите данные уравнения"); // Введите данные уравнения
            double a = RequestUserInputAsDouble("Введите число a:"); // Введите а
            double b = RequestUserInputAsDouble("Введите число b:"); // Введите b
            double c = RequestUserInputAsDouble("Введите число c:"); // Введите c
            Console.WriteLine("Ваше уравнение: " + a + "x^2 + " + b + "x + " + c + " = 0");
            double discriminant = CalculateDiscriminant(a, b, c);
    
            if (discriminant < 0) // Условие, если Дискриминант < 0
            {
                Console.WriteLine("Нет решений, т.к D < 0 "); // Вывод ответа
            }
            else if (discriminant > 0) // // Условие, если Дискриминант > 0
            {
                double x1 = (-b + Math.Sqrt(discriminant)) / (2 * a); // Обьявление переменной х1 и решение
                double x2 = (-b - Math.Sqrt(discriminant)) / (2 * a); // Обьявление переменной х2 и решение
                Console.WriteLine("Ваш ответ: x1 = " + x1 + " x2 = " + x2); // Вывод ответа
            }
            else // (D == 0)  Условие, если Дискриминант = 0
            {
                double x1 = (-b + Math.Sqrt(0)) / (2 * a); // Обьявление переменной х1 и решение
                double x2 = x1; // Обьявление переменной х2 и решение
                Console.WriteLine("Ваш ответ: x2 = x1 = " + x1); // Вывод ответа
            }
        }
    
        private double CalculateDiscriminant(double a, double b, double c)
        {
            // Вычисление переменной Дискриминант
            return b * b - (4 * a * c);
        }
    }


    Класс, который позволяет запросить ввод пользователя и если пользователь ввёл неверные данные, которые нельзя конвертировать в целевой тип данных, то ввод снова запрашивается у пользователя.
    using System.Globalization;
    
    namespace ConsoleApp;
    
    internal static class ConsoleInput
    {
        private static readonly CultureInfo CommaCulture =
            new(CultureInfo.InvariantCulture.LCID)
            {
                NumberFormat = { NumberDecimalSeparator = "," }
            };
        private static readonly CultureInfo PointCulture =
            new(CultureInfo.InvariantCulture.LCID)
            {
                NumberFormat = { NumberDecimalSeparator = "." }
            };
    
    
        /// <summary>
        /// Запросить ввод у пользователя. Если ввод нельзя конвертировать в целевой тип,
        /// то ввод будет запрошен повторно. Это обобщённый метод, позволящий реализовать 
        /// несколько других методов, требующих ввод в определённом формате.
        /// </summary>
        /// <typeparam name="TResult">
        /// Тип результата, который ожидается от метода конвертации.
        /// </typeparam>
        /// <param name="tryConvert">Ссылка на метод конвертации.</param>
        /// <param name="message">
        /// Сообщение, которое будет показано пользователю каждый новый запрос ввода значения.
        /// </param>
        /// <returns></returns>
        private static TResult RequestUserInput<TResult>(
            Func<string, (bool, TResult)> tryConvert, string? message = null)
            where TResult : struct
        {
            TResult result;
            while (true)
            {
                if (!string.IsNullOrWhiteSpace(message))
                {
                    Console.WriteLine(message);
                }
    
                string? line = Console.ReadLine();
                if (!string.IsNullOrWhiteSpace(line))
                {
                    var (success, convertedValue) = tryConvert(line);
                    if (success)
                    {
                        result = convertedValue;
                        break;
                    }
                }
            }
    
            return result;
        }
    
        /// <summary>
        /// Запросить у пользователя ввод числа типа double.
        /// Допускается в качестве разделителя "," и ".".
        /// </summary>
        /// <param name="message">
        /// Сообщение, которое будет показано пользователю каждый новый запрос ввода значения.
        /// </param>
        /// <returns></returns>
        public static double RequestUserInputAsDouble(string? message = null)
        {
            return RequestUserInput(userInput =>
            {
                CultureInfo culture = CultureInfo.InvariantCulture;
                if (userInput.Contains(",")) culture = CommaCulture;
                if (userInput.Contains(".")) culture = PointCulture;
                return double.TryParse(
                    userInput, NumberStyles.Float, culture, out var result)
                    ? (true, result)
                    : (false, 0d);
            }, message);
        }
    
        // И другие типы в том же духе
        public static int RequestUserInputAsInt32(string? message = null)
        {
            return RequestUserInput(userInput =>
                    int.TryParse(userInput, out var result)
                        ? (true, result)
                        : (false, 0),
                message);
        }
    }
    Ответ написан
    Комментировать
  • Как с одного массива данных внести данные из другого?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Если я всё правильно понял, то вот:

    Исходные данные:
    FirstReportInvoiceDal[] firstReportInvoice =
    {
        new () { Id = 1, Number = "" },
        new () { Id = 2, Number = "" },
        new () { Id = 3, Number = "" },
        new () { Id = 4, Number = "" },
        new () { Id = 5, Number = "" },
    };
    SecondReportInvoiceDal[] secondReportInvoice =
    {
        new () { FirstReportId = 1, Number = "1111N" },
        new () { FirstReportId = 2, Number = "2222N" },
        new () { FirstReportId = 3, Number = "3333N" },
        new () { FirstReportId = 4, Number = "4444N" },
        new () { FirstReportId = 5, Number = "5555N" },
    };


    Вывод:
    Id: 1, Number: 1111N
    Id: 2, Number: 2222N
    Id: 3, Number: 3333N
    Id: 4, Number: 4444N
    Id: 5, Number: 5555N


    namespace ConsoleApp;
    
    class Program
    {
        public static void Main(string[] args)
        {
            FirstReportInvoiceDal[] firstReportInvoice =
            {
                new () { Id = 1, Number = "" },
                new () { Id = 2, Number = "" },
                new () { Id = 3, Number = "" },
                new () { Id = 4, Number = "" },
                new () { Id = 5, Number = "" },
            };
            SecondReportInvoiceDal[] secondReportInvoice =
            {
                new () { FirstReportId = 1, Number = "1111N" },
                new () { FirstReportId = 2, Number = "2222N" },
                new () { FirstReportId = 3, Number = "3333N" },
                new () { FirstReportId = 4, Number = "4444N" },
                new () { FirstReportId = 5, Number = "5555N" },
            };
    
            ReportRow[] rows = CreateReportRows(firstReportInvoice, secondReportInvoice);
            Display(rows);
        }
    
        private static void Display(IEnumerable<ReportRow> rows)
        {
            foreach (ReportRow row in rows)
            {
                Console.WriteLine(row);
            }
        }
    
        static ReportRow[] CreateReportRows(FirstReportInvoiceDal[] firstReportInvoice,
            SecondReportInvoiceDal[] secondReportInvoice)
        {
            // Для быстрого поиска делаем словарь с ключом SecondReportInvoiceDal.FirstReportId,
            // который соответствует ключу FirstReportInvoiceDal.Id.
            var secondReportSet = secondReportInvoice.ToDictionary(x => x.FirstReportId);
    
            // Для каждого firstReportInvoice сделать трансформацию (LINQ метод Select)
            return firstReportInvoice.Select(x =>
            {
                var row = new ReportRow
                {
                    Id = x.Id,
                    Number = secondReportSet[x.Id].Number
                };
                return row;
                // Вызываем ToArray, чтобы запустилось выполнение трансформации в методе Select.
                // И чтобы в принципе мы вернули данные, а не итератор.
            }).ToArray();
        }
    }
    
    class FirstReportInvoiceDal
    {
        public int Id { get; init; }
    
        public string Number { get; init; }
    }
    
    class SecondReportInvoiceDal
    {
        public int FirstReportId { get; init; }
    
        public string Number { get; init; }
    }
    
    class ReportRow
    {
        public int Id { get; init; }
    
        public string Number { get; init; }
    
        public override string ToString()
        {
            return $"Id: {Id}, Number: {Number}";
        }
    }
    Ответ написан
    1 комментарий
  • Установка библиотеки из Git?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Файл build.gradle.kts (Kotlin). Читай ниже и смотри скриншоты.
    import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
    
    plugins {
        kotlin("jvm") version "1.7.0"
    }
    
    group = "org.example"
    version = "1.0-SNAPSHOT"
    
    repositories {
        maven {
            url = uri("https://jitpack.io")
        }
        mavenCentral()
    }
    
    dependencies {
        implementation("io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.0.7")
        testImplementation(kotlin("test"))
    }
    
    tasks.test {
        useJUnitPlatform()
    }
    
    tasks.withType<KotlinCompile> {
        kotlinOptions.jvmTarget = "1.8"
    }


    Файл build.gradle (Groovy)
    plugins {
        id 'org.jetbrains.kotlin.jvm' version '1.7.0'
    }
    
    group = 'org.example'
    version = '1.0-SNAPSHOT'
    
    repositories {
        maven { url "https://jitpack.io" }
        mavenCentral()
    }
    
    dependencies {
        implementation 'io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:6.0.7'
        testImplementation 'org.jetbrains.kotlin:kotlin-test'
    }
    
    test {
        useJUnitPlatform()
    }
    
    compileKotlin {
        kotlinOptions.jvmTarget = '1.8'
    }
    
    compileTestKotlin {
        kotlinOptions.jvmTarget = '1.8'
    }


    Создаём новый проект, где в качестве языка Gradle скриптов выбираем Kotlin (его банально легче понять, так как там всё типизировано и можно просто перейти и посмотреть исходник.
    62b23c308102b293725073.png

    Если проект использует для Gradle скриптов не Kotlin, а Groovy, то нужно нажать кнопку, на которую показывает стрелка. Может быть не во всех случаях так. В общем, по ситуации.
    62b23c5780200189084481.png

    Готово
    62b23cfdd078d277180730.png
    Ответ написан
  • Как исправить ошибку? "Переменная не инициализирована?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Исправил ошибку. Простым readLine здесь не обойтись. Написал функцию requestUserInputAsInt, которая перезапрашивает ввод у пользователя, если введено не число или введённое число не попадает в диапазон.

    В целом я понял, что хочет реализовать автор и здесь нужно всё писать по-другому, но это придёт с опытом. Например, для характеристик героя и мира используй классы. Для совершения действий в мире можно использовать State Machine, при том лучше реализовать её так, чтобы можно было все состояния расписать в одном месте в декларативном виде (все переходы состояний, сами состояния в отдельных классах).

    Первое, что нагуглил. В целом, похоже на то, что я имел ввиду:
    Implement a state machine with kotlin using tinders library (ссылка)
    https://github.com/Tinder/StateMachine

    62ac6d647890a259916233.png
    Вдруг кому-то интересно: подсветка синтаксиса называется Visual Studio 2019 Dark + я сам добавил свои модификации, чтобы было похоже на подсветку для C# из Visual Studio 2022 для тёмной темы для языка C#

    val newLine: String = System.lineSeparator()
    val menu: List<String> = listOf("Пиво", "Пахлёбка ", "Супец")
    
    fun main(args: Array<String>) {
    	val hearth: Int = 5
    	val projectName: String = "Мечи Средиземья"
    	val defaultSteed: String = "- Скакуна нет "
    	val traktirName: String = "Рог Единорога"
    	val buyManName: String = "Эдгар"
    	val moneySum: Int = 23
    	val hasSteed: String = defaultSteed
    	val heroName: String = "Дионис"
    
    	println(projectName)
    	println(hasSteed)
    	println("Здоровье: $hearth")
    	println("Монет: $moneySum")
    	println("Главный герой прибыл в трактир $traktirName ${newLine}Вас приветствует  владелец трактира $buyManName")
    
    	try {
    		val message = "Выберите действие:${newLine}Открыть Меню - 1${newLine}Посмотреть в зеркало - 2"
    		when (requestUserInputAsInt(message, IntRange(1, 2))) {
    			1 -> println("Меню: $menu")
    			2 -> println("В зеркале герой увидел свое имя $heroName")
    		}
    	} catch (ex: Throwable) {
    		ex.printStackTrace()
    		println(ex)
    	}
    }
    
    /**
     * Запросить ввод пользователем целого числа. В случае неправильного ввода запрос будет осуществлён повторно.
     * @param message Сообщение, которое будет выведено на консоль, при первом и повторных запросах ввода.
     * @param range диапазон чисел, в которые должен попасть пользовательский ввод.
     * */
    fun requestUserInputAsInt(message: String? = null, range: IntRange? = null): Int {
    
    	range?.let {
    		if (it.first > it.last) throw IllegalArgumentException("first > last: (${it.first} > ${it.last})")
    	}
    
    	val result: Int
    	while (true) {
    		message?.let { println(it) }
    		
    		val line = readlnOrNull()
    		if (!line.isNullOrBlank()) {
    			val resultTemp: Int? = line.toIntOrNull()
    			if (resultTemp != null) {
    				if (range != null) {
    					if (resultTemp >= range.first &&
    						resultTemp <= range.last
    					) {
    						result = resultTemp
    						break
    					}
    				} else {
    					result = resultTemp
    					break
    				}
    			}
    		}
    	}
    
    	return result
    }
    Ответ написан
  • Подсчет гласных букв. Почему ошибки?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Вот как-то так можно. Зачем здесь объявление алфавита? Да теперь его можно копипастить в каждый проект, что удобно. И соревнований по максимальной краткости, вроде бы, не объявляли.

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
    </Project>


    using System.Collections.ObjectModel;
    using System.Globalization;
    
    namespace VowelsCount;
    
    public class Program
    {
        static void Main(string[] args)
        {
            var letters = new List<Letter> {
                new ('а', LetterType.Vowel),
                new ('б', LetterType.Consonant),
                new ('в', LetterType.Consonant),
                new ('г', LetterType.Consonant),
                new ('д', LetterType.Consonant),
                new ('е', LetterType.Vowel),
                new ('ё', LetterType.Vowel),
                new ('ж', LetterType.Consonant),
                new ('з', LetterType.Consonant),
                new ('и', LetterType.Vowel),
                new ('й', LetterType.Consonant),
                new ('к', LetterType.Consonant),
                new ('л', LetterType.Consonant),
                new ('м', LetterType.Consonant),
                new ('н', LetterType.Consonant),
                new ('о', LetterType.Vowel),
                new ('п', LetterType.Consonant),
                new ('р', LetterType.Consonant),
                new ('с', LetterType.Consonant),
                new ('т', LetterType.Consonant),
                new ('у', LetterType.Vowel),
                new ('ф', LetterType.Consonant),
                new ('х', LetterType.Consonant),
                new ('ц', LetterType.Consonant),
                new ('ч', LetterType.Consonant),
                new ('ш', LetterType.Consonant),
                new ('щ', LetterType.Consonant),
                new ('ъ', LetterType.Consonant),
                new ('ы', LetterType.Vowel),
                new ('ь', LetterType.Consonant),
                new ('э', LetterType.Vowel),
                new ('ю', LetterType.Vowel),
                new ('я', LetterType.Vowel)
            };
    
            var alphabet = new Alphabet(letters);
            IReadOnlySet<char> vowels = alphabet.GetVowelSet();
            IReadOnlySet<char> consonants = alphabet.GetConsonantSet();
    
            const string text = "Да мы хотим помочь!!!";
    
            int vowelCounter = 0;
            int consonantCounter = 0;
    
            var vowelResult = new char[text.Length];
            var consonantResult = new char[text.Length];
            var otherSymbolsResult = new char[text.Length];
    
            var ruRu = new CultureInfo("ru-RU");
    
            for (int i = 0; i < text.Length; i++)
            {
                vowelResult[i] = '_';
                consonantResult[i] = '_';
                otherSymbolsResult[i] = '_';
    
                char lowerCaseChar = char.ToLower(text[i], ruRu);
                if (consonants.Contains(lowerCaseChar))
                {
                    ++consonantCounter;
                    consonantResult[i] = text[i];
                }
                else if (vowels.Contains(lowerCaseChar))
                {
                    ++vowelCounter;
                    vowelResult[i] = text[i];
                }
                else
                {
                    otherSymbolsResult[i] = text[i];
                }
            }
    
            Console.WriteLine("Исходная строка для подсчёта:");
            Console.WriteLine(text);
            Console.WriteLine("=========");
            Console.WriteLine(vowelResult);
            Console.WriteLine(consonantResult);
            Console.WriteLine(otherSymbolsResult);
            Console.WriteLine("=========");
            Console.WriteLine("Кол-во символов в исходной строке: " + text.Length);
            Console.WriteLine("Кол-во гласных: " + vowelCounter);
            Console.WriteLine("Кол-во согласных: " + consonantCounter);
            Console.WriteLine("Кол-во прочих символов: " +
                (text.Length - (vowelCounter + consonantCounter)));
        }
    }
    
    /// <summary>Тип буквы - гласная или согласная.</summary>
    internal enum LetterType
    {
        /// <summary>Гласная.</summary>
        Vowel,
    
        /// <summary>Согласная.</summary>
        Consonant
    }
    
    internal record struct Letter(char letter, LetterType type)
    {
        public LetterType Type { get; init; } = type;
    
        public char Value { get; init; } = letter;
    }
    
    internal class Alphabet
    {
        public IReadOnlyList<Letter> Letters { get; }
    
        public Alphabet(IEnumerable<Letter> letters)
        {
            Letters = letters switch
            {
                IList<Letter> list => new ReadOnlyCollection<Letter>(list),
                _ => new ReadOnlyCollection<Letter>(letters.ToList()),
            };
        }
    
        public IReadOnlyList<char> GetVowelList()
        {
            return Letters
                .Where(letter => letter.Type == LetterType.Vowel)
                .Select(letter => letter.Value)
                .ToList()
                .AsReadOnly();
        }
    
        public IReadOnlySet<char> GetVowelSet()
        {
            return Letters
                .Where(letter => letter.Type == LetterType.Vowel)
                .Select(letter => letter.Value)
                .ToHashSet();
        }
    
        public IReadOnlyList<char> GetConsonantList()
        {
            return Letters
                .Where(letter => letter.Type == LetterType.Consonant)
                .Select(letter => letter.Value)
                .ToList()
                .AsReadOnly();
        }
    
        public IReadOnlySet<char> GetConsonantSet()
        {
            return Letters
                .Where(letter => letter.Type == LetterType.Consonant)
                .Select(letter => letter.Value)
                .ToHashSet();
        }
    }
    Ответ написан
    6 комментариев
  • Функция swap заменить максимальные и минимальные значения массивов?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Обмен местами первых найденных минимальных значений в двух двумерных массивах.
    using System;
    
    namespace ConsoleApp
    {
        internal class Program
        {
            static void Main(string[] args)
            {
                int[,] arrayA = new int[3, 4]
                {
                    {5, 5, 50, 5},
                    {5, 5, 5, 5},
                    {5, 5, 5, 2},
                };
                int[,] arrayB = new int[4, 2]
                {
                    {5, 5},
                    {5, 1},
                    {15, 5},
                    {5, 1},
                };
    
                Console.WriteLine("Array A:");
                Print(arrayA);
    
                Console.WriteLine();
                Console.WriteLine("Array B:");
                Print(arrayB);
    
                Console.WriteLine();
                Console.WriteLine("Array A, first min value position:");
                var (yMinA, xMinA) = FindFirstMinValuePosition(arrayA);
                Print(xMinA, yMinA);
    
                Console.WriteLine();
                Console.WriteLine("Array B, first min value position:");
                var (yMinB, xMinB) = FindFirstMinValuePosition(arrayB);
                Print(xMinB, yMinB);
    
                Console.WriteLine();
                Console.WriteLine("Array A, first max value position:");
                var (yMaxA, xMaxA) = FindFirstMaxValuePosition(arrayA);
                Print(xMaxA, yMaxA);
    
                Console.WriteLine();
                Console.WriteLine("Array B, first max value position:");
                var (yMaxB, xMaxB) = FindFirstMaxValuePosition(arrayB);
                Print(xMaxB, yMaxB);
    
                Swap(arrayA, arrayB, yMinA, xMinA, yMinB, xMinB);
                Swap(arrayA, arrayB, yMaxA, xMaxA, yMaxB, xMaxB);
    
                Console.WriteLine("----");
                Console.WriteLine();
                Console.WriteLine("Array A after two swaps:");
                Print(arrayA);
    
                Console.WriteLine();
                Console.WriteLine("Array B after two swaps:");
                Print(arrayB);
    
                Console.WriteLine();
            }
    
            private static void Swap(int[,] arrayA, int[,] arrayB, int yA, int xA, int yB, int xB)
            {
                int tempB = arrayB[yB, xB];
                arrayB[yB, xB] = arrayA[yA, xA];
                arrayA[yA, xA] = tempB;
            }
    
            private static (int y, int x) FindFirstMinValuePosition(int[,] array)
            {
                if (array is null) throw new ArgumentNullException(nameof(array));
    
                int y = array.GetLength(0);
                int x = array.GetLength(1);
    
                if (y == 0) throw new InvalidOperationException(
                    "The dimension of the array along the Y axis is zero.");
                if (x == 0) throw new InvalidOperationException(
                    "The dimension of the array along the X axis is zero.");
    
                int yResult = 0;
                int xResult = 0;
    
                int minValue = array[0, 0];
                for (int yIndex = 0; yIndex < y; yIndex++)
                {
                    for (int xIndex = 0; xIndex < x; xIndex++)
                    {
                        if (minValue > array[yIndex, xIndex])
                        {
                            yResult = yIndex;
                            xResult = xIndex;
                            minValue = array[yIndex, xIndex];
                        }
                    }
                }
    
                return (yResult, xResult);
            }
    
            private static (int y, int x) FindFirstMaxValuePosition(int[,] array)
            {
                if (array is null) throw new ArgumentNullException(nameof(array));
    
                int y = array.GetLength(0);
                int x = array.GetLength(1);
    
                if (y == 0) throw new InvalidOperationException(
                    "The dimension of the array along the Y axis is zero.");
                if (x == 0) throw new InvalidOperationException(
                    "The dimension of the array along the X axis is zero.");
    
                int yResult = 0;
                int xResult = 0;
    
                int maxValue = array[0, 0];
                for (int yIndex = 0; yIndex < y; yIndex++)
                {
                    for (int xIndex = 0; xIndex < x; xIndex++)
                    {
                        if (maxValue < array[yIndex, xIndex])
                        {
                            yResult = yIndex;
                            xResult = xIndex;
                            maxValue = array[yIndex, xIndex];
                        }
                    }
                }
    
                return (yResult, xResult);
            }
    
            private static void Print(int x, int y)
            {
                Console.WriteLine($"x: {x}, y: {y}");
            }
    
            private static void Print(int[,] array)
            {
                int x = array.GetLength(0);
                int y = array.GetLength(1);
    
                for (int xIndex = 0; xIndex < x; xIndex++)
                {
                    for (int yIndex = 0; yIndex < y; yIndex++)
                    {
                        Console.Write($"{array[xIndex, yIndex]}, ");
                    }
                    Console.WriteLine();
                }
            }
        }
    }


    Вывод программы:
    Array A:
    5, 5, 50, 5,
    5, 5, 5, 5,
    5, 5, 5, 2,
    
    Array B:
    5, 5,
    5, 1,
    15, 5,
    5, 1,
    
    Array A, first min value position:
    x: 3, y: 2
    
    Array B, first min value position:
    x: 1, y: 1
    
    Array A, first max value position:
    x: 2, y: 0
    
    Array B, first max value position:
    x: 0, y: 2
    ----
    
    Array A after two swaps:
    5, 5, 15, 5,
    5, 5, 5, 5,
    5, 5, 5, 1,
    
    Array B after two swaps:
    5, 5,
    5, 2,
    50, 5,
    5, 1,
    Ответ написан
    3 комментария
  • Имя i не существует в текущем контексте?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Не написал в цикле int. Если это "оптимизация", то не нужно заниматься ерундой. Переменная будет видна внутри области видимости, в которой она объявлена, и внутри вложенных областей видимости, так сказать. Снаружи нет.
    for (int i = 0; i < arraySize; i++)
    {
        // Используй всегда скобки. Вот опыт тебя уже научил, что без них ты получил ошибку.
    }


    Код должен выглядеть как-то так, без учёта валидации ввода и запроса по новой. Здесь больше про именование переменных и про наличие фигурных скобок у for.
    // Program.cs
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Введите n");
                int arraySize = int.Parse(Console.ReadLine());
    
                int[] array = new int[arraySize];
                Console.WriteLine("Введите массив А");
    
                for (int i = 0; i < arraySize; i++)
                {
                    array[i] = int.Parse(Console.ReadLine());
                }
    
                int max = array[0];
                for (int i = 0; i < arraySize; i++)
                {
                    if (array[i] > max) 
                        max = array[i];
    
                    Console.Write(array[i] + " ");
                }
                
    
                Console.ReadLine();
            }
        }


    Ещё бы посоветовал избавиться от стремления написать как можно больше кода в одну строку. Это бессмысленное занятие.
    Ответ написан
    1 комментарий
  • Как сделать асинхронный while цикл?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    ConsoleApp\Program.cs
    // See https://aka.ms/new-console-template for more information
    
    await DoWork();
    
    async Task DoWork()
    {
        int counter = 0;
        while (true)
        {
            Console.WriteLine($"TEST {++counter}");
            await Task.Delay(900);
        }
    }


    ConsoleApp\ConsoleApp.csproj
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
    </Project>
    Ответ написан
    Комментировать
  • Как работает array.indices?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Удалился индекс 2, то есть элемент коллекции под индексом 2.
    index: 0: value: 1
    index: 1: value: 2
    index: 2: value: 3
    index: 3: value: 4
    index: 4: value: 5

    Если удалить индекс 2, то элемент 3 выведен не будет. Кажется логичным.

    Я открыл IntelliJ IDEA, зажал Ctrl (Cmd в MacOS) и нажал левой кнопкой мыши на знак - (минус). Попал в метод-расширение minus. Скопировал его и другие связанные методы. Получил точно такое же поведение (потому что фактически выполняется тот же самый код). Теперь можно начать отлаживать код, пройтись по методам пошагово и понять почему мы имеем такой результат. Ранее упомянутый метод minus - это метод, которого нет в исходном классе Iterable<T>, но его добавили в какой-то библиотеке. Это не новшество Kotlin, такие же методы-расширения можно создавать, например, в C#.

    623f0a3e1643d280918242.png

    fun main(args: Array<String>) {
    
        val numbers = intArrayOf(1, 2, 3, 4, 5)
    
        // Исходный пример
        for (index in numbers.indices - 2) {
            println("index: $index: value: ${numbers[index]}")
        }
    
        println("------")
    
        // Пример-объяснение. Были взяты оригинальные методы расширения
        // и вынесены сюда для удобства отладки и наглядности.
        for (index in minus(numbers.indices, 2)) {
            println("index: $index: value: ${numbers[index]}")
        }
    }
    
    fun <T> minus(iterable: Iterable<T>, element: T): List<T> {
        val arraySize = collectionSizeOrDefault(iterable, 10)
        val result = ArrayList<T>(arraySize)
        var removed = false
        return filterTo(iterable, result) {
            if (!removed && it == element) {
                removed = true; false
            } else true
        }
    }
    
    fun <T> collectionSizeOrDefault(iterable: Iterable<T>, default: Int): Int =
        if (iterable is Collection<*>) iterable.size else default
    
    fun <T, C : MutableCollection<in T>> filterTo(iterable: Iterable<T>, destination: C, predicate: (T) -> Boolean): C {
        for (element in iterable) if (predicate(element)) destination.add(element)
        return destination
    }


    Лучше вынести из выражение, чтобы удобнее было дебажить и смотреть, что там к чему:
    val result: List<Int> = minus(numbers.indices, 2)
        for (index in result) {
            println("index: $index: value: ${numbers[index]}")
        }


    Вывод:
    index: 0: value: 1
    index: 1: value: 2
    index: 3: value: 4
    index: 4: value: 5
    ------
    index: 0: value: 1
    index: 1: value: 2
    index: 3: value: 4
    index: 4: value: 5
    Ответ написан
    1 комментарий
  • Вопрос про изучение C# – оптимальная методика?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Нормально. Я так и учил C#. Практика важна в этом деле, без неё долго будешь учить. Только я писал WPF приложение. И вообще практика написания больших приложений учит строить архитектуру. Будешь писать код и видеть проблемы в своём проекте. Рефакторить проект. Переписывать его части.
    Ответ написан
    2 комментария
  • Происходит Destroy нескольких врагов вместо одного?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Сработал OnCollisionEnter, нанёс первому персонажу урон. Ушёл от первого персонажа, но у него hitByPlayer == true как был, так и остался. Ты атакуешь второго персонажа. Урон наносится сразу обоим игрокам.

    Видимо, надо в OnCollisionExit вызывать
    hitByPlayer = false;
    Ответ написан
    1 комментарий
  • C# - плавающий глюк - насколько правильно исправил?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Подпишись на событие FormClosing (если ещё не подписан) и в его обработчике отпишись от обработчиков событий TitleChanged, AddressChanged, LoadingStateChanged:
    public partial class BrowserMain : Form
    {
        public BrowserMain()
        {
            InitializeComponent();
            
            WebBrowser = new ChromiumWebBrowser(
                string.IsNullOrWhiteSpace(address) ? "about:blank" : address)
            {
                // ...
            };
    
            Controls.Add(WebBrowser);
    
            WebBrowser.TitleChanged += WebBrowser_TitleChanged;
            WebBrowser.AddressChanged += WebBrowser_AddressChanged;
            WebBrowser.LoadingStateChanged += webBrowser_DocumentCompleted;
        }
    
        private void BrowserMain_FormClosing(object sender, FormClosingEventArgs e)
        {
           // После вызова этих строк методы WebBrowser_TitleChanged, WebBrowser_AddressChanged
           // и webBrowser_DocumentCompleted не будут выполняться. 
           // Это и не нужно, так как окно закрывается.
            WebBrowser.TitleChanged -= WebBrowser_TitleChanged;
            WebBrowser.AddressChanged -= WebBrowser_AddressChanged;
            WebBrowser.LoadingStateChanged -= webBrowser_DocumentCompleted;
        }
    }
    Ответ написан
    3 комментария
  • С чего начать изучение C#?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Советую заглянуть в базу знаний для .NET разработчиков (будет пополняться)
    Ответ написан
    Комментировать
  • Как работать с wpf анимацией?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    При её нажатии на кнопку снизу всплывает надпись и исчезает. В контрол можно поместить, что угодно, не только текст. Остальной код в комментариях.

    MainWindow.xaml.cs
    using System.Windows;
    
    namespace Notification
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void OnButtonClick(object sender, RoutedEventArgs e)
            {
                _notification.Activate();
            }
        }
    }


    Controls/NotificationControl.cs
    using System.Windows;
    using System.Windows.Controls;
    
    namespace Notification.Controls
    {
        public class NotificationControl : ContentControl
        {
            public NotificationControl()
            {
                DefaultStyleKey = typeof(NotificationControl);
            }
    
            public void Activate()
            {
                VisualStateManager.GoToState(this, "Default", false);
                VisualStateManager.GoToState(this, "Activated", true);
            }
        }
    }


    Resources/Styles.xaml
    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:Notification.Controls">
    
        <KeyTime x:Key="OffsetYKeyTime">0:0:0.8</KeyTime>
        <KeyTime x:Key="OpacityDelayKeyTime">0:0:1.8</KeyTime>
        <KeyTime x:Key="VisibilityDelayKeyTime">0:0:2.2</KeyTime>
        <Style TargetType="controls:NotificationControl">
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="VerticalAlignment" Value="Stretch" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="controls:NotificationControl">
                        <Border
                            x:Name="RootElement"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Opacity="0"
                            Visibility="Collapsed">
                            <ContentPresenter
                                x:Name="ContentPresenter"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                <ContentPresenter.RenderTransform>
                                    <TransformGroup>
                                        <TranslateTransform />
                                        <RotateTransform />
                                    </TransformGroup>
                                </ContentPresenter.RenderTransform>
                            </ContentPresenter>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Default">
                                        <Storyboard>
    
                                            <DoubleAnimationUsingKeyFrames
                                                Storyboard.TargetName="ContentPresenter"
                                                Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)">
                                                <EasingDoubleKeyFrame
                                                    KeyTime="0:0:0"
                                                    Value="0">
                                                </EasingDoubleKeyFrame>
                                            </DoubleAnimationUsingKeyFrames>
    
                                            <DoubleAnimationUsingKeyFrames
                                                Storyboard.TargetName="RootElement"
                                                Storyboard.TargetProperty="Opacity">
                                                <EasingDoubleKeyFrame
                                                    KeyTime="0:0:0"
                                                    Value="1">
                                                </EasingDoubleKeyFrame>
                                            </DoubleAnimationUsingKeyFrames>
    
                                            <ObjectAnimationUsingKeyFrames
                                                Storyboard.TargetName="RootElement"
                                                Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
    
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Activated">
                                        <Storyboard>
    
                                            <DoubleAnimationUsingKeyFrames
                                                Storyboard.TargetName="ContentPresenter"
                                                Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)">
                                                <EasingDoubleKeyFrame
                                                    KeyTime="0:0:0"
                                                    Value="0">
                                                    <EasingDoubleKeyFrame.EasingFunction>
                                                        <QuadraticEase EasingMode="EaseOut" />
                                                    </EasingDoubleKeyFrame.EasingFunction>
                                                </EasingDoubleKeyFrame>
                                                <EasingDoubleKeyFrame
                                                    KeyTime="{StaticResource OffsetYKeyTime}"
                                                    Value="-80">
                                                    <EasingDoubleKeyFrame.EasingFunction>
                                                        <QuadraticEase EasingMode="EaseOut" />
                                                    </EasingDoubleKeyFrame.EasingFunction>
                                                </EasingDoubleKeyFrame>
                                            </DoubleAnimationUsingKeyFrames>
    
                                            <DoubleAnimationUsingKeyFrames
                                                Storyboard.TargetName="RootElement"
                                                Storyboard.TargetProperty="Opacity">
                                                <EasingDoubleKeyFrame
                                                    KeyTime="0:0:0"
                                                    Value="1">
                                                    <EasingDoubleKeyFrame.EasingFunction>
                                                        <QuadraticEase EasingMode="EaseInOut" />
                                                    </EasingDoubleKeyFrame.EasingFunction>
                                                </EasingDoubleKeyFrame>
                                                <EasingDoubleKeyFrame
                                                    KeyTime="{StaticResource OpacityDelayKeyTime}"
                                                    Value="0">
                                                    <EasingDoubleKeyFrame.EasingFunction>
                                                        <QuadraticEase EasingMode="EaseInOut" />
                                                    </EasingDoubleKeyFrame.EasingFunction>
                                                </EasingDoubleKeyFrame>
                                            </DoubleAnimationUsingKeyFrames>
    
                                            <ObjectAnimationUsingKeyFrames
                                                Storyboard.TargetName="RootElement"
                                                Storyboard.TargetProperty="Visibility">
                                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                                <DiscreteObjectKeyFrame KeyTime="{StaticResource VisibilityDelayKeyTime}">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
    
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    Ответ написан
  • Как в C# (.NET) задать значение возвращаемого методом значения через ref, используя reflection?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    using System;
    using System.Diagnostics;
    using System.Reflection;
    
    namespace ConsoleApp
    {
        class Program
        {
            private delegate ref int GetMaxNumber(ref int value1, ref int value2);
    
            static void Main(string[] args)
            {
                int value1 = 5;
                int value2 = 10;
                var instance = new Something();
    
                MethodInfo? methodInfo = typeof(Something).GetMethod(
                    nameof(Something.GetMax), BindingFlags.Public | BindingFlags.Instance);
                Debug.Assert(methodInfo is not null);
                var setNumber = (GetMaxNumber)Delegate.CreateDelegate(typeof(GetMaxNumber), instance, methodInfo);
    
                setNumber.Invoke(ref value1, ref value2) = 50;
    
                Console.WriteLine($"{nameof(value1)}: {value1}, {nameof(value2)}: {value2}");
            }
        }
    
        public class Something
        {
            public ref int GetMax(ref int left, ref int right)
            {
                if (left > right)
                {
                    return ref left;
                }
    
                return ref right;
            }
        }
    }


    Проверял на
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
    </Project>
    Ответ написан
    Комментировать