Pass a ref
jika Anda ingin mengubah objek itu:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
Setelah memanggil DoSomething, t
tidak merujuk ke yang asli new TestRef
, tetapi merujuk ke objek yang sama sekali berbeda.
Ini mungkin berguna juga jika Anda ingin mengubah nilai objek yang tidak dapat diubah, misalnya a string
. Anda tidak dapat mengubah nilai string
setelah itu dibuat. Tetapi dengan menggunakan ref
, Anda bisa membuat fungsi yang mengubah string untuk yang lain yang memiliki nilai berbeda.
Sunting: Seperti orang lain sebutkan. Ini bukan ide yang baik untuk digunakan ref
kecuali jika diperlukan. Menggunakan ref
memberikan kebebasan metode untuk mengubah argumen untuk sesuatu yang lain, penelepon metode perlu diberi kode untuk memastikan mereka menangani kemungkinan ini.
Juga, ketika tipe parameter adalah objek, maka variabel objek selalu bertindak sebagai referensi ke objek. Ini berarti bahwa ketika ref
kata kunci digunakan, Anda punya referensi ke referensi. Ini memungkinkan Anda untuk melakukan hal-hal seperti yang dijelaskan dalam contoh yang diberikan di atas. Tetapi, ketika tipe parameter adalah nilai primitif (misalnya int
), maka jika parameter ini ditugaskan dalam metode, nilai argumen yang diteruskan akan diubah setelah metode kembali:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
ref
di situs panggilan juga ... di mana lagi Anda ingin dibedakan? Semantiknya juga cukup jelas, tetapi perlu diekspresikan dengan hati-hati (alih-alih "objek dilewatkan dengan referensi" yang merupakan penyederhanaan berlebihan yang umum).Di .NET saat Anda meneruskan parameter apa pun ke suatu metode, salinan dibuat. Dalam tipe nilai berarti bahwa modifikasi apa pun yang Anda lakukan pada nilai ada di ruang lingkup metode, dan hilang ketika Anda keluar dari metode.
Saat melewati Jenis Referensi, salinan juga dibuat, tetapi itu adalah salinan referensi, yaitu sekarang Anda memiliki DUA referensi dalam memori ke objek yang sama. Jadi, jika Anda menggunakan referensi untuk memodifikasi objek, itu akan dimodifikasi. Tetapi jika Anda memodifikasi referensi itu sendiri - kita harus ingat itu adalah salinan - maka setiap perubahan juga hilang saat keluar dari metode.
Seperti yang dikatakan orang sebelumnya, tugas adalah modifikasi dari referensi, sehingga hilang:
Metode di atas tidak mengubah objek asli.
Sedikit modifikasi contoh Anda
sumber
Karena TestRef adalah kelas (yang merupakan objek referensi), Anda dapat mengubah konten di dalam t tanpa meneruskannya sebagai referensi. Namun, jika Anda lulus t sebagai ref, TestRef dapat mengubah apa yang t merujuk asli. yaitu membuatnya menunjuk ke objek yang berbeda.
sumber
Dengan
ref
Anda dapat menulis:Dan t akan diubah setelah metode selesai.
sumber
Pikirkan variabel (misalnya
foo
) dari jenis referensi (misalnyaList<T>
) sebagai pengenal objek memegang bentuk "Objek # 24601". Misalkan pernyataanfoo = new List<int> {1,5,7,9};
menyebabkanfoo
menahan "Objek # 24601" (daftar dengan empat item). Kemudian panggilanfoo.Length
akan menanyakan Object # 24601 untuk panjangnya, dan itu akan menjawab 4, sehinggafoo.Length
akan sama dengan 4.Jika
foo
diteruskan ke metode tanpa menggunakanref
, metode itu mungkin membuat perubahan ke Objek # 24601. Sebagai konsekuensi dari perubahan tersebut,foo.Length
mungkin tidak lagi sama 4. Metode itu sendiri, bagaimanapun, tidak akan dapat berubahfoo
, yang akan terus memegang "Objek # 24601".Melewati
foo
sebagairef
parameter akan memungkinkan metode yang dipanggil untuk melakukan perubahan tidak hanya untuk Objek # 24601, tetapi juga untukfoo
dirinya sendiri. Metode ini dapat membuat Object # 8675309 baru dan menyimpan referensi itu difoo
. Jika demikian,foo
tidak akan lagi memegang "Object # 24601", melainkan "Object # 8675309".Dalam praktiknya, variabel tipe referensi tidak memiliki string dari bentuk "Object # 8675309"; mereka bahkan tidak memiliki apa pun yang secara bermakna dapat diubah menjadi angka. Meskipun setiap variabel tipe referensi akan menampung beberapa pola bit, tidak ada hubungan tetap antara pola bit yang disimpan dalam variabel tersebut dan objek yang mereka identifikasi. Tidak ada cara kode dapat mengekstraksi informasi dari suatu objek atau referensi ke sana, dan kemudian menentukan apakah referensi lain mengidentifikasi objek yang sama, kecuali jika kode tersebut memiliki atau mengetahui referensi yang mengidentifikasi objek asli.
sumber
Ini seperti melewatkan pointer ke pointer di C. Dalam. NET ini akan memungkinkan Anda untuk mengubah apa yang T asli merujuk, secara pribadi meskipun saya pikir jika Anda melakukan itu di. NET Anda mungkin punya masalah desain!
sumber
Dengan menggunakan
ref
kata kunci dengan tipe referensi, Anda secara efektif menyampaikan referensi ke referensi. Dalam banyak hal itu sama dengan menggunakanout
kata kunci tetapi dengan perbedaan kecil bahwa tidak ada jaminan bahwa metode tersebut benar-benar akan menetapkan apa pun keref
parameter 'ed.sumber
ref
meniru (atau berperilaku) sebagai area global hanya untuk dua lingkup:sumber
Namun, jika Anda memberikan nilai, segalanya berbeda. Anda dapat memaksa nilai untuk dilewatkan dengan referensi. Ini memungkinkan Anda untuk mengirim bilangan bulat ke metode, misalnya, dan meminta metode memodifikasi bilangan bulat atas nama Anda.
sumber
Ref menunjukkan apakah fungsi bisa mendapatkan objek itu sendiri, atau hanya pada nilainya.
Melewati dengan referensi tidak terikat pada suatu bahasa; itu adalah strategi pengikatan parameter di sebelah nilai demi nilai, pass by name, pass by need, dll ...
A sidenote: nama kelas
TestRef
adalah pilihan yang sangat buruk dalam konteks ini;).sumber