==============
ОНОВЛЕННЯ: Цю відповідь я використав як основу для цього запису в блозі:
Чому параметри 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 Tiger
into n
, що є псевдонімом для x
.
- На іншій темі хтось пише
Turtle
вx
.
N
намагається прочитати вміст n
та виявляє a Turtle
у тому, що, на його думку, є змінною типу Mammal
.
Зрозуміло, ми хочемо зробити це незаконним.
Висновок 4 : out
параметри не можна робити "більшими".
Остаточний висновок : Ні, ref
ніout
параметри, параметри не можуть змінюватися залежно від типу. Інакше - порушити безпеку типу, що перевіряється.
Якщо ці проблеми в теорії базових типів вас цікавлять, розгляньте, прочитавши мою серію про те, як працюють коваріація та протиріччя в C # 4.0 .