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);