형식변환 수행 없이 자식클래스 메소드 호출 지원
부모클래스에서 사용하는 변수명으로 자식클래스에 변수를 선언하는 것
new키워드를 붙여 새로 선언한다.
class Parent
{
    public int a { get; set; } = 1234;
}
class Child : Parent
{
    public new string a { get; set; } = "one-two-three-four";
}
class Program {
    static void Main(string[] args)
    {
        Child child = new Child();
        Console.WriteLine(child.a); // one-two-three-four
        Console.WriteLine(((Parent)child).a); // 1234
    }
}부모클래스에서 사용하는 메소드명으로 자식클래스에 메소드를 선언하는 것
new키워드를 붙여 새로 선언한다.
class Parent
{
    public void A()
    {
        Console.WriteLine("Parent");
    }
}
class Child : Parent
{
    public new void A()
    {
        Console.WriteLine("Child");
    }
}
class Program {
    static void Main(string[] args)
    {
        Child child = new Child();
        child.A(); // Child
        ((Parent)child).A(); // Parent
    }
}자식 클래스에서 부모 클래스의 메소드를 재정의 하는 것. 다형성 지원을 위한 핵심 기능
virtual, 자식클래스 메소드에 override 키워드 사용.class Parent
{
    public virtual void Say() { Console.WriteLine("Parent"); }
}
class Child_1 : Parent
{
    public override void Say()
    {
        Console.WriteLine("Child_1");
    }
}
class Child_2 : Parent
{
    public override void Say()
    {
        Console.WriteLine("Child_2");
    }
}
class Child_3 : Parent
{
    public override void Say()
    {
        base.Say();
        Console.WriteLine("Child_3");
    }
}
class Program {
    static void Main(string[] args)
    {
        Parent[] items = new Parent[] { new Child_1(), new Child_2(), new Child_3() };
        foreach (Parent item in items)
        {
            item.Say();
            // Child_1
            // Child_2
            // Parent
            // Child_3
        }
    }
}'재정의된 메소드를 갖고있는 자식객체'를 부모클래스로 형변환하고, Say()를 호출한다.
하이딩 메소드를 갖고있는 객체는 부모클래스의 메소드를 실행한다.
오버라이딩 메소드를 갖고있는 객체는 재정의된 자신의 메소드를 실행한다.
class Parent
{
    public virtual void Say() { Console.WriteLine("Parent"); }
}
class Child_Hiding : Parent
{
    public new void Say()
    {
        Console.WriteLine("Child_Hiding");
    }
}
class Child_Overriding : Parent
{
    public override void Say()
    {
        Console.WriteLine("Child_Overriding");
    }
}
class Program {
    static void Main(string[] args)
    {
        Parent[] items = new Parent[] { new Child_Hiding(), new Child_Overriding() };
        foreach (Parent item in items)
        {
            item.Say();
            // Parent
            // Child_Overriding
        }
    }
}오버라이드한 메소드에 sealed키워드를 사용할 수 있다.
이 메소드를 포함한 클래스를 상속한 자식은, 이 메소드를 오버라이드 할 수 없다.
class Parent {
    public virtual void A() { }
}
class Child : Parent
{
    public sealed override void A() { }
}
class ChildChild : Child
{
    // 컴파일에러
    // public override void A() { }
}Object클래스의 메소드 중 Equals(), ToString()에 대해 살펴보면, virtual메소드로 정의가 되어있다.
즉, Object를 상속하는 클래스에서 오버라이딩 할 수 있다.
public class Object {
    public virtual bool Equals() { /* .. */}
    public virtual string ToString() { /* .. */}
    // ...
}재정의 예시
public class Gorani
{
    public string? Name { get; set; }
    public string? ID { get; set; }
    public override bool Equals(object? input)
    {
        Gorani? g = input as Gorani;
        if (g == null)
        {
            return false;
        }
        else
        {
            return Name == g.Name;
        }
    }
    public override string ToString()
    {
        return $"Name : {Name} / ID : {ID}";
    }
}
class Program
{
    static void Main(string[] args)
    {
        Gorani a = new Gorani() { Name = "a", ID = "001" };
        Gorani b = new Gorani() { Name = "b", ID = "053" };
        Console.WriteLine(a.Equals(b));
        Console.WriteLine(a.ToString());
        Console.WriteLine(b.ToString());
        Console.WriteLine(a);
        Console.WriteLine(b);
    }
}메소드 뿐 아니라 연산자도 오버로딩 할 수 있다.
아래와 같은 형태로 사용한다.
public static 클래스명 operator 연산자(인수){
  return 반환값;
}아래는 + 연산자를 오버로딩한 예시이다.
public class Gorani
{
    public double noisy { get; set; }
    public static Gorani operator +(Gorani op1, Gorani op2)
    {
            return new Gorani() { noisy = op1.noisy + op2.noisy };
    }
    public override string ToString()
    {
        return noisy + "DB";
    }
}
class Program
{
    static void Main(string[] args)
    {
        Gorani a = new Gorani() { noisy = 53 };
        Gorani b = new Gorani() { noisy = 5353};
        Gorani c = a + b;
        Console.WriteLine(a + b); // 5406DB
        Console.WriteLine(c); // 5406DB
    }
}