C# commonly demonstrates compile-time polymorphism through overload resolution and run-time polymorphism through virtual dispatch or interface dispatch. Parametric polymorphism through generics is also important because one algorithm works safely with many types. ```csharp public sealed class PriceFormatter { public string Format(decimal value) => value.ToString("0.00"); public string Format(decimal value, string currency) => $"{currency} {value:0.00}"; // compile-time overload selection } public interface IDiscount { decimal Apply(decimal subtotal); } public sealed class PercentageDiscount(decimal rate) : IDiscount { public decimal Apply(decimal subtotal) => subtotal * (1 - rate); } static T Last<T>(IReadOnlyList<T> values) => values[^1]; // generic ``` When `IDiscount.Apply` is called, the runtime selects the concrete implementation. Overloading selects the best compatible signature at compile time. Method hiding with `new` is not overriding: selection depends on the reference's compile-time type, so it is usually less suitable for substitutable behavior.
Prince Yadav · · 0 likes