برای پارامترهای نوع جنریک، کلمه کلیدی out مشخص می کند که پارامتر نوع covariant است. شما می توانید از کلیدواژه out در رابط های جنریک و وکیل ها استفاده کنید.
کواریانس این توانایی را به شما می دهد که از نوع بیشتر مشتق شده (غیر پایه ای تر، از ریشه دورتر) نسبت به آن نوعی که پارامتر جنریک تعیین کرده استفاده کنید. این تکنیک اجازه تبدیل ضمنی کلاس هایی که اینترفیس های گوناگون را پیاده سازی کرده اند و همچنین تبدیل ضمنی نوع های وکالتی را می دهد.
رابطی که دارای پارامتر نوع covariant است، به متدهایش این امکان را می دهد که نوع هایی بیشتر مشتق شده نسبت به آنهایی که توسط پارامتر نوع مشخص شده، برگشت دهند. برای مثال، چون در دات نت فریم وورک 4، در <IEnumerable<T ، نوع T کواریانت است، شما می توانید شیئی از نوع (IEnumerable(of String را به شیئی از نوع (IEnumerable(of Object انتساب دهید، بدون اینکه به هیچ متد تبدیل خاصی نیاز داشته باشید.
یک وکیل (delegate) کواریانت می تواند به وکیل های دیگر از نوع یکسان انتساب داده شود ، ولی با یک پارامتر نوع جنریک بیشتر مشتق شده.
مثال
مثال زیر چگونگی اعلان، توسعه (ارث بری و بیشتر مشتق کردن) و پیاده سازی یک رابط جنریک (عام/وابسته به جنس) کواریانت را نشان می دهد. این مثال همچنین چگونگی استفاده از تبدیل ضمنی برای کلاس هایی که یک رابط کواریانت را پیاده سازی می کنند ، نشان می دهد.
// Covariant interface. interface ICovariant<out R> { } // Extending covariant interface. interface IExtCovariant<out R> : ICovariant<R> { } // Implementing covariant interface. class Sample<R> : ICovariant<R> { } class Program { static void Test() { ICovariant<Object> iobj = new Sample<Object>(); ICovariant<String> istr = new Sample<String>(); // You can assign istr to iobj because // the ICovariant interface is covariant. iobj = istr; } }
در یک رابط جنریک، اگر یک پارامتر نوع دارای شرایط زیر باشد، می تواند بصورت کواریانت اعلان شود:
- پارامتر نوع فقط به عنوان نوع برگشتی متدهای رابط استفاده شده باشد و به عنوان نوع آرگومان های متد استفاده نشده باشد.
نکته
برای این قانون یک استثناء وجود دارد. اگر در این رابط کواریانت یک وکیل جنریک کنتراواریانت به عنوان پارامتر متد دارید، می توانید برای این وکیل از نوع کواریانت به عنوان پارامتر نوع جنریک استفاده کنید.
- پارامتر نوع به عنوان یک قید (constraint) جنریک برای متد های رابط استفاده نشود.
مثال زیر چگونگی اعلان، نمونه سازی و احضار (invoke) یک وکیل جنریک کواریانت را نشان می دهد. همچنین چگونگی تبدیل ضمنی نوع های وکالتی را نشان می دهد.
// Covariant delegate. public delegate R DCovariant<out R>(); // Methods that match the delegate signature. public static Control SampleControl() { return new Control(); } public static Button SampleButton() { return new Button(); } public void Test() { // Instantiate the delegates with the methods. DCovariant<Control> dControl = SampleControl; DCovariant<Button> dButton = SampleButton; // You can assign dButton to dControl // because the DCovariant delegate is covariant. dControl = dButton; // Invoke the delegate. dControl(); }
در یک وکیل جنریک، یک نوع را می توان بصورت کواریانت اعلان کرد، اگر آن نوع فقط به عنوان نوع برگشتی متد استفاده شده باشد و به عنوان آرگومان های متد مورد استفاده قرار نگرفته باشد.