Задать вопрос
  • Почему переопределение в C# работает так?

    @majstar_Zubr
    C++, C#, gamedev
    public class Class2
        {
            public string GetVal(int a, int b)
            {
                return "base";
            }
    
            public override string ToString()
            {
                return "_Class2_";
            }
        }


    public class Class3 : Class2
        {
    
            
            public string GetVal(int a, int b, bool defaultpar = true)
            {
                return "child with bool";
            }
    
            public new string GetVal(int a, int b)
            {
                return "child";
            }
    
            public override string ToString()
            {
                return "_Class3_";
            }
        }


    class Program
        {
            static void Main(string[] args)
            {
                Class2 obj_reference_c2 = new Class2();
                Class3 obj_reference_c3 = new Class3();
                Class2 obj_reference_assigned = obj_reference_c3;
                Class2 obj_reference_casted = (Class2)obj_reference_c3;
    
                Console.WriteLine($"Вызов - {obj_reference_c2} c параметрами 1, 2 : {obj_reference_c2.GetVal(1, 2)}");
                Console.WriteLine($"Вызов - {obj_reference_c3} c параметрами 1, 2 : {obj_reference_c3.GetVal(1, 2)}");
                Console.WriteLine($"Вызов {obj_reference_c3} c параметрами 1, 2 true: {obj_reference_c3.GetVal(1, 2, true)}");
    
                Console.WriteLine($"Вызов Class3 присвоенного по ссылке типа Class2 - {obj_reference_assigned} c параметрами 1, 2: {obj_reference_assigned.GetVal(1, 2)}");
                Console.WriteLine($"Вызов Class3 приведенного к типу Class2 - {obj_reference_casted} c параметрами 1, 2: {obj_reference_casted.GetVal(1, 2)}");
    
                /*      
                Вариант 1: в Class3 метод public string GetVal(int a, int b) {return "child";} закомментирован
    
                    Вызов - _Class2_ c параметрами 1, 2 : base
                    Вызов - _Class3_ c параметрами 1, 2 : child with bool
                    Вызов _Class3_ c параметрами 1, 2 true: child with bool
                    Вызов Class3 присвоенного по ссылке типа Class2 - _Class3_ c параметрами 1, 2: base
                    Вызов Class3 приведенного к типу Class2 - _Class3_ c параметрами 1, 2: base
    
                 */
    
                /*
                  Вариант 2: в Class3 метод public string GetVal(int a, int b) {return "child";} существует и прячет унаследованный член Class2.GetVal(int,int)
                
                    Вызов - _Class2_ c параметрами 1, 2 : base
                    Вызов - _Class3_ c параметрами 1, 2 : child
                    Вызов _Class3_ c параметрами 1, 2 true: child with bool
                    Вызов Class3 присвоенного по ссылке типа Class2 - _Class3_ c параметрами 1, 2: base
                    Вызов Class3 приведенного к типу Class2 - _Class3_ c параметрами 1, 2: base
    
                    в подобном случае требуется явно указывать в объявлении модификатор new:
                       public new string GetVal(int a, int b) {return "child";}
                 */
                Console.ReadLine();
            }
        }


    В вашем примере 1 не происходит перегрузка метода базового класса.
    Метод базового класса можно перекрыть ( public new string Foo() ) или переопределить, если базовый метод виртуальный.

    Перегруженные методы существуют только в одной области видимости, которая в C# ограничена классами.

    С точки зрения .Net, методы с сигнатурами string _ (int,int) и string _ (int,int,bool) разные, но синтаксически, в случае, если в методе string _ (int,int,bool) третий параметр снабжается параметром по умолчанию, не существует явного способа вызова, кроме Named Arguments.

    public class Class2
        {
            public string GetVal(int a, int b)
            {
                return "base";
            }
    
            public override string ToString()
            {
                return "_Class2_";
            }
        }
    
        public class Class3 : Class2
        {
            public new string GetVal(int a, int b)
            {
                return "child";
            }
    
            public string GetVal(int A, int B, bool defaultpar = true)
            {
                return "child with bool";
            }
    
            public override string ToString()
            {
                return "_Class3_";
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Class2 obj_reference_c2 = new Class2();
                Class3 obj_reference_c3 = new Class3();
                Class2 obj_reference_assigned = obj_reference_c3;
                Class2 obj_reference_casted = (Class2)obj_reference_c3;
    
                Console.WriteLine($"Вызов - {obj_reference_c2} c параметрами 1, 2 : {obj_reference_c2.GetVal(1, 2)}");
                Console.WriteLine($"Вызов - {obj_reference_c3} c параметрами 1, 2 : {obj_reference_c3.GetVal(1, 2)}");
                Console.WriteLine($"Вызов - {obj_reference_c3} c параметрами 1, 2 : {obj_reference_c3.GetVal(A:1, B:2)}");
                Console.WriteLine($"Вызов {obj_reference_c3} c параметрами 1, 2 true: {obj_reference_c3.GetVal(1, 2, true)}");
    
                Console.WriteLine($"Вызов Class3 присвоенного по ссылке типа Class2 - {obj_reference_assigned} c параметрами 1, 2: {obj_reference_assigned.GetVal(1, 2)}");
                Console.WriteLine($"Вызов Class3 приведенного к типу Class2 - {obj_reference_casted} c параметрами 1, 2: {obj_reference_casted.GetVal(1, 2)}");
    
                /*
                   
                Вариант 1Б: в Class3 метод public string GetVal(int a, int b) {return "child";} закомментирован
    
                    Вызов - _Class2_ c параметрами 1, 2 : base
                    Вызов - _Class3_ c параметрами 1, 2 : child with bool
                    Вызов - _Class3_ c параметрами 1, 2 : child with bool
                    Вызов _Class3_ c параметрами 1, 2 true: child with bool
                    Вызов Class3 присвоенного по ссылке типа Class2 - _Class3_ c параметрами 1, 2: base
                    Вызов Class3 приведенного к типу Class2 - _Class3_ c параметрами 1, 2: base
    
                 */
    
                /*
    
               Вариант 2Б: в Class3 метод public string GetVal(int a, int b) {return "child";} существует и прячет базовый
    
                    Вызов - _Class2_ c параметрами 1, 2 : base
                    Вызов - _Class3_ c параметрами 1, 2 : child
                    Вызов - _Class3_ c параметрами 1, 2 : child with bool
                    Вызов _Class3_ c параметрами 1, 2 true: child with bool
                    Вызов Class3 присвоенного по ссылке типа Class2 - _Class3_ c параметрами 1, 2: base
                    Вызов Class3 приведенного к типу Class2 - _Class3_ c параметрами 1, 2: base
    
                */
    
                Console.ReadLine();
            }
        }


    Данный пример не очень показателен с точки зрения использования named arguments.
    Для этого потребуется несколько аргументов со значениями по умолчанию.

    Хотя я рекомендую никогда не использовать значения по умолчанию, вместо этого стоит делать SOLID классы со специализированными методами и понятным API, а named arguments позволяют фривольно писать код в отрыве от порядка аргументов в сигнатуре, хоть задом наперед: c.GetVal( defaultpar: false, B: 42, A: 777);
    Ответ написан
    1 комментарий
  • C# Как сделать перенос строки после определенного количества символов в строке?

    arxont
    @arxont
    C# программист
    Попробуйте так (для примера взял текст вашего вопроса и размер строки в 50, а не 300)
    string sourceString = "Есть текст нужно чтобы. через каждые 300 символов искал запятую, точку, пробел и т.д (Искал не после 300 символов а именно в этом отрезке 0 - 300 или например 300 - 600) и после этого символа(запятой, точки, пробела и т.д.) делал перенос строки и так далее. Я хочу вывести это через Label, я знаю что есть вариант с Textbox но он мне не подходит.";
    int length = 50;
    char[] charsForEOL = { '.', ',', ' ' };
    string resultString = "";
    
    label1.Text = sourceString;
    
    do
    {
        for (int i = length; i >= 1; i--)
        {
            if (charsForEOL.Contains(sourceString[i]))
            {
                    resultString += sourceString.Substring(0, i) + "\n";
                    sourceString = sourceString.Substring(i + 1);
                    break;
            }
            if(i == 1)
            {
                    resultString += sourceString.Substring(0, length) + "\n";
                    sourceString = sourceString.Substring(length + 1);
            }
        }
    } while (sourceString.Length > length);
    
    resultString += sourceString;
    
    label2.Text = resultString;

    21c9fc023e8fd6f98d8cf43aa41f8ef261b216e6
    Ответ написан
    Комментировать