با سلام
اتفاقا این بحث,داغ ترین وجذاب ترین بحث در سی شارپ می باشد.
مثال آقا مهدی خیلی خوب بود .خواستم در مورد این مثال توضیحاتی بدم.فرض کنیم رییس این کارخانه دو حقوق دارد.یکی حقوق کارمندی خودش ودیگری حقوق سمت رییس.

متد محاسبه حقوق بصورت مجازی در کلاس والد Employee تعریف می شود و دربقیه کلاس ها هم این متد برای هر نوع کارمند جداگانه و با روش دیگری محاسبه میشود.سلسه مراتب
این کلاس ها به اینصورت هست.

class Employee
{
public virtual long CalcPayment()
{محاسبه حقوق}
}
class DayEmployee:Employee
{
public override long CalcPayment()
{
base.CalcPayment();
}
محاسبه حقوق
}
class Manager : DayEmployee
{
public override long CalcPayment()
{
base.CalcPayment();
}
محاسبه حقوق
}

اگر بخواهیم حقوق Manager رو محاسبه کنیم باید یه شئ از این کلاس بسازیم و متد
CalcPayment رو صدا بزنیم.در این صورت شئ Manager باید برای محاسبه حقوق خودش متد CalcPayment از کلاس DayEmployee رو هم صدا بزنه چون یه مدیر بهر حال یه کارمندم هست.این راه حل فقط تا زمانی کار می کند که ما ترتیب وراثت رو بهم نزنیم.یعنی اگر بین کلاس DayEmployee و کلاس Manger یه کلاس دیگه ایجاد کنیم ,این روش محاسبه حقوق کار آمد نمیباشد.برای حل این مشکل میتوانیم سلسله مراتب وراثتی بالا رو اینطور تغییر بدیم.

class Employee
{
public virtual long CalcPayment()
{محاسبه حقوق}
}
class DayEmployee:Employee
{
public override long CalcPayment()
{محاسبه حقوق}
}
class Manager : DayEmployee
{
public new virtual long CalcPayment()
{محاسبه حقوق}
}


حالا اگه در تابع اصلی اینطور بنویسیم حقوق مدیر بدرستی محاسبه میشود.

DayEmployee d = new DayEmployee();
Manager m = new Manager();
long all = m.CalcPayment() + d.CalcPayment();

اگر بجای متد محاسبه حقوق درشکل دوم , متد محاسبه حقوق در شکل اول رو می نوشتیم
خطوط اول و سوم از قطعه کد بالا متد CalcPayment از کلاس Manager رو فراخوانی میکرد.(در صورتیکه این کد برای فرم اول نوشته میشد.)و حقوق به اشتباه دو بار محاسبه میشد.
سی شارپ در برخورد با متدهای مجازی و تحریف شده اینطور عمل میکنه:
همیشه آخرین پیاده سازی از متد موجود در کلاس پایه فراخوانی میشود.در این فراخوانی ملاک,شئ پایه در سمت چپ مساوی است و شئ سمت راست تاثیری در فراخوانی ندارد.
با استفاده از این قاعده کلی به بررسی قطعه کد بالا می پردازیم.
1-کلاس پایه در این خط کلاس DayEmployee میباشد.پس آخرین پیاده سازی که مد نظر است متد CalcPayment از کلاس DayEmployee میباشد.

2-کلاس پایه در این خط کلاسManager میباشد.پس آخرین پیاده سازی که مد نظر است متد CalcPayment از کلاس Manager میباشد.
با توجه به این قاعده قطعه کدهای زیر نتایج یکسانی را بدست میدهند(حقوق, صحیح محاسبه میشود ).

Employee d = new DayEmployee();
Manager m = new Manager();
long all = m.CalcPayment() + d.CalcPayment();

و

Employee d = new Manager();
Manager m = new Manager();
long all = m.CalcPayment() + d.CalcPayment();

و

DayEmployee d = new Manager();
Manager m = new Manager();
long all = m.CalcPayment() + d.CalcPayment();

این انعطاف پذیری ها در فراخوانی متدهای مجازی نشانه پلی مورفیسم موفق در سی شارپ می باشد.