با عرض سلام و وقت بخیر خدمت کاربران سایت پی وی لرن ، با یکی دیگر از جلسات دوره کامل آموزش #C در خدمت شما دوستان هستیم . در بخش قبلی با متغیرهای Nullable آشنا شدید ، در این بخش قصد داریم شما را با مفهوم همبستگی در #C یا Covariance در سی شارپ آشنا کنیم. تا پایان این جلسه با ما همراه باشید.
کوواریانس و قراردادنویسی سلسله مراتب کلاس ها را تعیین می کند.
قبل از اینکه در مورد کواریانس و قراردادنویسی (contravariance) صحبت کنیم ، سلسله مراتب کلاس زیر را در نظر می گیریم:
1 2 3 4 5 6 7 8 9 10 11 12 | class Small { } class Big: Small { } class Bigger : Big { } |
همانطور که در مثال بالا مشخص است، کلاس small کلاس پایه برای big و big نیز یک کلاس پایه برای bigger است. نکته اینجا است که یک کلاس مشتق شده همیشه چیزی بیش از یک کلاس پایه دارد، بنابراین کلاس پایه نسبتا کوچکتر از کلاس مشتق شده است.
حالا مقادیر زیر را در نظر بگیرید:
همانطور که در بالا مشاهده می کنید، یک کلاس پایه می تواند یک کلاس مشتق شده داشته باشد، اما یک کلاس مشتق شده نمی تواند کلاس پایه را نگه دارد. به عبارت دیگر، یک نمونه می تواند از کلاس بزرگتر از خود تشکیل شود و نمیتواند کلاس کوچک تر از خودش را مورد استفاده قرار دهد.
کوواریانس شما را قادر می سازد تا یک کلاس مشتق شده را که در آن کلاس پایه بکار رفته است منتقل کنید .
کوواریانس (هموردایی) یک توسعهی چندریختی (Polymorfism) از آرایهها،delegate ، و جنریکها است و تبدیل مرجع ضمنی را برای آرایهها، delegate و پارامترهای نوع جنریک ارائه میکند. هموردایی باعث حفظشدن سازگاری انتساب میشود.
کوواریانس را می توان در delegate ، generic ، آرایه، رابط و … اعمال کرد.
کوواریانس در Delegate ها اجازه می دهد انعطاف پذیری در نوع بازگشتی از متدهای Delegate بیشتر باشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public delegate Small covarDel(Big mc); class Program { static Big Method1(Big bg) { Console.WriteLine("Method1"); return new Big(); } static Small Method2(Big bg) { Console.WriteLine("Method2"); return new Small(); } static void Main(string[] args) { covarDel del = Method1; Small sm = del(new Big()); } } |
خروجی :
1 2 | Method1 Method2 |
همانطور که در مثال بالا می بینید، delegate انتظار نوع بازگشتی small (کلاس پایه) را دارد، اما ما هنوز می توانیم Method1 را که بازگشتی Big(کلاس مشتق شده) است و همچنین Method2 را که در ساختار delegate است نشان دهیم .
بنابراین، کوواریانس اجازه می دهد تا شما یک متد را به delegate اختصاص دهید که دارای نوع بدون بازگشتی مشتق شده است.
Contravariane به پارامترها اعمال می شود. Cotravariance اجازه می دهد تا یک متد با پارامتر یک کلاس پایه به delegate اختصاص داده شود که انتظار می رود پارامتر یک کلاس مشتق شده باشد.
با ادامه مثال فوق، Method3 را که دارای نوع پارامتر دیگری از delegate است اضافه کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | delegate Small covarDel(Big mc); class Program { static Big Method1(Big bg) { Console.WriteLine("Method1"); return new Big(); } static Small Method2(Big bg) { Console.WriteLine("Method2"); return new Small(); } static Small Method3(Small sml) { Console.WriteLine("Method3"); return new Small(); } static void Main(string[] args) { covarDel del = Method1; del += Method2; del += Method3; Small sm = del(new Big()); } |
خروجی :
1 2 3 | Method1 Method2 Method3 |
همانطور که می بینید، Method3 دارای پارامتری از کلاس Small است در حالی که delegate انتظار یک پارامتر از کلاس Big را دارد. با این حال، می توانید از Method3 با delegate استفاده کنید.
شما همچنین می توانید با استفاده از covariance و contravariance در متد مشابه زیر استفاده کنید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | delegate Small covarDel(Big mc); class Program { static Big Method4(Small sml) { Console.WriteLine("Method3"); return new Big(); } static void Main(string[] args) { covarDel del = Method4; Small sm = del(new Big()); } } |
خروجی :
1 | Method4 |
یک کلاس والد مانند Animal را مانند زیر در نظر بگیرید:
1 2 3 4 5 6 7 8 9 10 11 12 | class Animal { public virtual int Get2 { set; get; } public virtual void Get1() { Console.WriteLine("Animal"); } } |
کلاس فرزند را که از کلاس Animal ارثبری میکند با عنوان Dog را هم مانند زیر در نظر بگیرید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Dog : Animal { public int num; public Dog(){} public Dog(int a) { num = a; } public override int Get2 { get { return num; } } public override void Get1() { Console.WriteLine("Dog"); } } |
حالا به طریق زیر می توانیم از این دو کلاس استفاده کنیم :
1 2 3 4 5 6 7 8 | class Program { static void Main(string[] args) { Animal objAnimal = new Dog(); } } |
در مثال بالا سگ یک حیوان است ، پس میتوان از کلاس animal ارث بری کند.
حالا به مثال زیر دقت کنید :
1 2 3 4 5 6 7 8 9 10 11 12 13 | Dog ob1 = new Dog(1); Dog ob2 = new Dog(2); Dog ob3 = new Dog(3); Dog ob4 = new Dog(4); List<Dog> list = new List<Dog>(); list.Add(ob1); list.Add(ob2); list.Add(ob3); list.Add(ob4); IEnumerable<Animal> obAnimal = new List<Dog>(); |
شی obAnimal در .NET نسخهی ۳٫۵ خطا را برمی گرداند زیرا در این نسخه هموردایی (covariance) فعال نمی باشد ولی در نسخه NET 4. به بعد به طور خودکار خاصیت هموردایی فعالب بوده و کدهای بالا خطا نمی دهند.
در این بخش با خاصیت هموردایی (covariance) در زبان #C آشنا شدید ، در بخش بعدی قصد داریم شما را با متغیر های نوع var در #C آشنا کنیم.