==============
ОНОВЛЕННЯ: Цю відповідь я використав як основу для цього запису в блозі:
Чому параметри ref і out не дозволяють змінювати тип?
Дивіться сторінку блогу, щоб отримати додатковий коментар до цього питання. Дякую за чудове запитання.
==============
Давайте припустимо , що у вас є класи Animal, Mammal, Reptile, Giraffe, TurtleіTiger , з очевидними відносинами підкласів.
Тепер припустимо, у вас є метод void M(ref Mammal m). Mможе і читати, і писати m.
Ви можете передати змінну типу Animalв M?
Ні. Ця змінна може містити A Turtle, але Mприпустимо, що вона містить лише ссавців. А Turtleне є Mammal.
Висновок 1 : refпараметри не можна робити "більшими". (Тут більше тварин, ніж ссавців, тому змінна стає "більшою", оскільки вона може містити більше речей.)
Ви можете передати змінну типу Giraffeв M?
Ні, Mможна писати m, і, Mможливо, захоче написати Tigerв m. Тепер ви помістили Tigerзмінну, яка є власне типом Giraffe.
Висновок 2 : refпараметри не можна робити "меншими".
Тепер розглянемо N(out Mammal n).
Ви можете передати змінну типу Giraffeв N?
Ні, Nможна писати на n, а Nможливо, захоче написати Tiger.
Висновок 3 : outпараметри не можна робити "меншими".
Ви можете передати змінну типу Animalв N?
Хм.
Ну чому б і ні? Nне вміє читати n, він може писати лише це, правда? Ви пишете a Tigerдо змінної типу Animalі все готово, правда?
Неправильно. Правило не " Nможе писати лише в n".
Короткі правила:
1) Nповинен написати nдо Nповернення в звичайному режимі. (Якщо Nкидає, всі ставки відключені.)
2) Nмає щось написати до того, nяк воно щось прочитає n.
Це дозволяє цю послідовність подій:
- Оголосити поле
xтипу Animal.
- Передати
xяк outпараметр до N.
Nпише a Tigerinto n, що є псевдонімом для x.
- На іншій темі хтось пише
Turtleвx .
Nнамагається прочитати вміст nта виявляє a Turtleу тому, що, на його думку, є змінною типу Mammal.
Зрозуміло, ми хочемо зробити це незаконним.
Висновок 4 : outпараметри не можна робити "більшими".
Остаточний висновок : Ні, refніout параметри, параметри не можуть змінюватися залежно від типу. Інакше - порушити безпеку типу, що перевіряється.
Якщо ці проблеми в теорії базових типів вас цікавлять, розгляньте, прочитавши мою серію про те, як працюють коваріація та протиріччя в C # 4.0 .