Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Nota
Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.
Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut ditangkap dalam catatan terkait rapat desain bahasa (LDM) .
Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .
Edisi Unggulan: https://github.com/dotnet/csharplang/issues/7706
Ringkasan
Kami memperkenalkan atribut baru, System.Runtime.CompilerServices.OverloadResolutionPriority, yang dapat digunakan oleh penulis API untuk menyesuaikan prioritas relatif overload dalam satu tipe sebagai sarana untuk mengarahkan konsumen API agar menggunakan API tertentu, bahkan jika API tersebut biasanya dianggap ambigu atau tidak akan dipilih oleh aturan resolusi overload C#.
Motivasi
Penulis API sering mengalami masalah tentang apa yang harus dilakukan dengan anggota setelah usang. Untuk tujuan kompatibilitas ke belakang, banyak yang akan menjaga anggota yang ada dengan ObsoleteAttribute diatur ke kesalahan selamanya, untuk menghindari gangguan pada konsumen yang memperbarui biner saat runtime. Ini terutama menekan sistem plugin, di mana penulis plugin tidak mengontrol lingkungan tempat plugin berjalan. Pembuat lingkungan mungkin ingin menyimpan metode lama yang ada, tetapi memblokir akses ke lingkungan tersebut untuk kode yang baru dikembangkan. Namun, ObsoleteAttribute dengan sendirinya tidak cukup. Jenis atau anggota masih terlihat dalam resolusi kelebihan beban, dan dapat menyebabkan kegagalan resolusi kelebihan beban yang tidak diinginkan ketika ada alternatif yang sangat baik, tetapi alternatif itu ambigu dengan anggota yang usang, atau keberadaan anggota yang usang menyebabkan resolusi kelebihan beban berakhir lebih awal tanpa pernah mempertimbangkan anggota yang baik. Untuk tujuan ini, kami ingin memiliki cara bagi penulis API untuk memandu resolusi kelebihan beban dalam menyelesaikan ambiguitas, sehingga mereka dapat mengembangkan area permukaan API mereka dan mengarahkan pengguna ke API berkinerja tanpa harus membahayakan pengalaman pengguna.
Tim Pustaka Kelas Dasar (BCL) memiliki beberapa contoh di mana ini dapat terbukti berguna. Beberapa contoh (hipotetis) adalah:
- Membuat kelebihan beban
Debug.Assertyang menggunakanCallerArgumentExpressionuntuk mendapatkan ekspresi yang ditegaskan, sehingga dapat disertakan dalam pesan, dan membuatnya lebih disukai daripada kelebihan beban yang ada. - Membuat
string.IndexOf(string, StringComparison = Ordinal)lebih disukai daripadastring.IndexOf(string). Ini harus dibahas sebagai potensi perubahan besar yang berpotensi mengganggu, tetapi ada pemikiran bahwa ini adalah default yang lebih baik, dan lebih mungkin menjadi yang diinginkan pengguna. - Kombinasi dari proposal ini dan
CallerAssemblyAttributeakan memungkinkan metode yang memiliki identitas pemanggil implisit untuk menghindari stack walk yang mahal.Assembly.Load(AssemblyName)melakukan ini hari ini, dan itu bisa jauh lebih efisien. -
Microsoft.Extensions.Primitives.StringValuesmengungkapkan adanya konversi implisit kestringdanstring[]. Ini berarti situasinya menjadi ambigu ketika diteruskan ke metode dengan overloadparams string[]danparams ReadOnlySpan<string>. Atribut ini dapat digunakan untuk memprioritaskan salah satu kelebihan beban untuk mencegah ambiguitas.
Desain Terperinci
Prioritas resolusi kelebihan beban
Kami mendefinisikan konsep baru, overload_resolution_priority, yang digunakan selama proses menyelesaikan grup metode.
overload_resolution_priority adalah nilai bilangan bulat 32-bit. Semua metode memiliki overload_resolution_priority sebesar 0 sebagai default, dan dapat diubah dengan menerapkan OverloadResolutionPriorityAttribute pada suatu metode. Kami memperbarui bagian §12.6.4.1 dari spesifikasi C# sebagai berikut (diubah menjadi huruf tebal):
Setelah anggota fungsi kandidat dan daftar argumen diidentifikasi, pemilihan anggota fungsi terbaik sama dalam semua kasus:
- Pertama, kumpulan anggota fungsi kandidat dikurangi menjadi anggota fungsi yang berlaku sehubungan dengan daftar argumen yang diberikan (§12.6.4.2). Jika set yang telah dikurangi ini kosong, terjadi kesalahan waktu kompilasi.
- Kemudian, set kandidat yang telah dikurangi dikelompokkan berdasarkan jenis deklarasi. Dalam setiap grup:
- Anggota fungsi kandidat diurutkan oleh overload_resolution_priority. Jika anggota adalah penggantian, overload_resolution_priority berasal dari deklarasi anggota yang paling dasar.
- Semua anggota yang memiliki overload_resolution_priority lebih rendah daripada yang tertinggi yang ditemukan dalam grup jenis pendeklarasinya dihapus.
- Grup yang dikurangi kemudian dikombinasikan ulang ke dalam set akhir anggota fungsi kandidat yang berlaku.
- Kemudian, anggota fungsi terbaik dari kumpulan kandidat fungsi yang berlaku ditemukan. Jika set hanya berisi satu anggota fungsi, maka anggota fungsi tersebut adalah anggota fungsi terbaik. Jika tidak, anggota fungsi terbaik adalah satu anggota fungsi yang lebih baik daripada semua anggota fungsi lainnya sehubungan dengan daftar argumen yang diberikan, asalkan setiap anggota fungsi dibandingkan dengan semua anggota fungsi lain menggunakan aturan dalam §12.6.4.3. Jika tidak ada tepat satu anggota fungsi yang lebih baik daripada semua anggota fungsi lainnya, maka pemanggilan anggota fungsi menjadi ambigu dan terjadi kesalahan saat waktu pengikatan.
Sebagai contoh, fitur ini akan menyebabkan cuplikan kode berikut menampilkan "Span", bukan "Array".
using System.Runtime.CompilerServices;
var d = new C1();
int[] arr = [1, 2, 3];
d.M(arr); // Prints "Span"
class C1
{
[OverloadResolutionPriority(1)]
public void M(ReadOnlySpan<int> s) => Console.WriteLine("Span");
// Default overload resolution priority
public void M(int[] a) => Console.WriteLine("Array");
}
Seperti pemangkasan untuk jenis turunan terbanyak, efek dari perubahan ini adalah bahwa kami menambahkan pemangkasan akhir untuk prioritas resolusi kelebihan muatan. Karena pemangkasan ini terjadi pada akhir proses resolusi kelebihan beban, itu berarti bahwa jenis dasar tidak dapat membuat anggotanya lebih prioritas daripada jenis turunan apa pun. Ini disengaja, dan mencegah terjadinya perlombaan senjata di mana jenis dasar dapat mencoba untuk selalu lebih baik daripada jenis turunan. Misalnya:
using System.Runtime.CompilerServices;
var d = new Derived();
d.M([1, 2, 3]); // Prints "Derived", because members from Base are not considered due to finding an applicable member in Derived
class Base
{
[OverloadResolutionPriority(1)]
public void M(ReadOnlySpan<int> s) => Console.WriteLine("Base");
}
class Derived : Base
{
public void M(int[] a) => Console.WriteLine("Derived");
}
Angka negatif diizinkan untuk digunakan, dan dapat digunakan untuk menandai kelebihan beban tertentu sebagai lebih buruk dari semua kelebihan beban default lainnya.
overload_resolution_priority anggota berasal dari deklarasi paling sedikit dari anggota itu.
overload_resolution_priority tidak diwariskan atau disimpulkan dari anggota antarmuka apa pun yang dapat diimplementasikan oleh anggota tipe, dan ketika terdapat anggota Mx yang mengimplementasikan anggota antarmuka Mi, tidak ada peringatan yang dikeluarkan jika Mx dan Mi memiliki overload_resolution_priorityyang berbeda.
NB: Niat aturan ini adalah untuk mereplikasi perilaku pengubah
params.
System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute
Kami memperkenalkan atribut berikut ke BCL:
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class OverloadResolutionPriorityAttribute(int priority) : Attribute
{
public int Priority => priority;
}
Semua metode dalam C# memiliki prioritas default overload_resolution_priority dari 0, kecuali jika diberi atribut OverloadResolutionPriorityAttribute. Jika mereka dikaitkan dengan atribut tersebut, maka overload_resolution_priority adalah nilai bilangan bulat yang diberikan kepada argumen pertama dari atribut tersebut.
Ini adalah kesalahan untuk menerapkan OverloadResolutionPriorityAttribute di lokasi-lokasi berikut:
- Properti bukan pengindeks
- Pengakses properti, pengindeks, atau peristiwa
- Operator konversi
- Lambda
- Fungsi lokal
- Finalizer
- Konstruktor statis
Atribut yang ditemui di lokasi ini dalam metadata diabaikan oleh C#.
Ini adalah kesalahan untuk menerapkan OverloadResolutionPriorityAttribute pada lokasi yang akan diabaikan, seperti pada penggantian metode dasar, karena prioritas diambil dari deklarasi anggota yang paling dasar.
NB: Ini sengaja berbeda dari perilaku pengubah
params, yang memungkinkan penetapan ulang atau penambahan saat diabaikan.
Panggilan anggota
Peringatan penting untuk OverloadResolutionPriorityAttribute adalah bahwa hal itu dapat membuat anggota tertentu secara efektif tidak dapat dipanggil dari kode sumber. Misalnya:
using System.Runtime.CompilerServices;
int i = 1;
var c = new C3();
c.M1(i); // Will call C3.M1(long), even though there's an identity conversion for M1(int)
c.M2(i); // Will call C3.M2(int, string), even though C3.M1(int) has less default parameters
class C3
{
public void M1(int i) {}
[OverloadResolutionPriority(1)]
public void M1(long l) {}
[Conditional("DEBUG")]
public void M2(int i) {}
[OverloadResolutionPriority(1), Conditional("DEBUG")]
public void M2(int i, [CallerArgumentExpression(nameof(i))] string s = "") {}
public void M3(string s) {}
[OverloadResolutionPriority(1)]
public void M3(object o) {}
}
Untuk contoh-contoh ini, prioritas default yang berlebihan secara efektif menjadi tidak berarti, dan hanya dapat dipanggil melalui beberapa langkah yang memerlukan upaya tambahan.
- Mengonversi metode menjadi deleget, lalu menggunakan deleget tersebut.
- Untuk beberapa skenario variansi jenis referensi, seperti
M3(object)yang diprioritaskan daripadaM3(string), strategi ini kemungkinan besar akan gagal. - Metode kondisional, seperti
M2, juga tidak akan dapat dipanggil dengan strategi ini, karena metode kondisional tidak dapat dikonversi ke delegasi.
- Untuk beberapa skenario variansi jenis referensi, seperti
- Menggunakan fitur runtime
UnsafeAccessoruntuk memanggilnya melalui tanda tangan yang cocok. - Menggunakan refleksi secara manual untuk mendapatkan referensi ke metode dan kemudian memanggilnya.
- Kode yang tidak dikompilasi ulang akan terus memanggil metode lama.
- IL tulisan tangan dapat menentukan apa saja yang diinginkannya.
Buka Pertanyaan
Pengelompokan metode ekstensi (dijawab)
Seperti yang saat ini dirumuskan, metode ekstensi diurutkan berdasarkan prioritas hanya dalam tipe mereka sendiri. Misalnya:
new C2().M([1, 2, 3]); // Will print Ext2 ReadOnlySpan
static class Ext1
{
[OverloadResolutionPriority(1)]
public static void M(this C2 c, Span<int> s) => Console.WriteLine("Ext1 Span");
[OverloadResolutionPriority(0)]
public static void M(this C2 c, ReadOnlySpan<int> s) => Console.WriteLine("Ext1 ReadOnlySpan");
}
static class Ext2
{
[OverloadResolutionPriority(0)]
public static void M(this C2 c, ReadOnlySpan<int> s) => Console.WriteLine("Ext2 ReadOnlySpan");
}
class C2 {}
Saat melakukan resolusi kelebihan beban untuk anggota ekstensi, sebaiknya kita tidak mengurutkan dengan mendeklarasikan jenis, dan sebaliknya mempertimbangkan semua ekstensi dalam cakupan yang sama?
Menjawab
Kami akan selalu mengelompokkan. Contoh di atas akan mencetak Ext2 ReadOnlySpan
Pewarisan atribut pada penimpaan (dijawab)
Haruskah atribut diwariskan? Jika tidak, apa prioritas anggota yang menggantikan?
Jika atribut ditentukan pada anggota virtual, haruskah penimpaan anggota tersebut diperlukan untuk mengulangi atribut?
Menjawab
Atribut tidak akan ditandai sebagai diwariskan. Kami akan melihat deklarasi anggota yang paling tidak diturunkan untuk menentukan prioritas resolusi kelebihan bebannya.
Kesalahan atau peringatan aplikasi saat mengambil alih (dijawab)
class Base
{
[OverloadResolutionPriority(1)] public virtual void M() {}
}
class Derived
{
[OverloadResolutionPriority(2)] public override void M() {} // Warn or error for the useless and ignored attribute?
}
Apa yang seharusnya kita lakukan pada penerapan OverloadResolutionPriorityAttribute dalam konteks di mana ia diabaikan, seperti pengecualian:
- Jangan lakukan apa-apa, biarkan diam-diam diabaikan.
- Terbitkan peringatan bahwa atribut akan diabaikan.
- Munculkan kesalahan bahwa atribut tidak diizinkan.
3 adalah pendekatan yang paling berhati-hati, jika kita mempertimbangkan kemungkinan di masa depan di mana kita ingin melakukan override untuk menentukan atribut ini.
Menjawab
Kami akan menggunakan 3, dan memblokir aplikasi di lokasi di mana aplikasi tersebut akan diabaikan.
Implementasi antarmuka implisit (dijawab)
Apa perilaku implementasi antarmuka implisit? Apakah perlu menentukan OverloadResolutionPriority? Apa perilaku pengkompilasi ketika menemukan implementasi implisit tanpa prioritas? Ini hampir pasti akan terjadi, karena pustaka antarmuka dapat diperbarui, tetapi bukan implementasi. Seni sebelumnya di sini dengan params tidak menentukan, dan tidak membawa nilai:
using System;
var c = new C();
c.M(1, 2, 3); // error CS1501: No overload for method 'M' takes 3 arguments
((I)c).M(1, 2, 3);
interface I
{
void M(params int[] ints);
}
class C : I
{
public void M(int[] ints) { Console.WriteLine("params"); }
}
Pilihan kami adalah:
- Ikuti
params.OverloadResolutionPriorityAttributetidak akan dibawa secara implisit atau perlu ditentukan. - Gunakan atribut secara implisit.
- Jangan bawa atribut secara implisit; pastikan atribut tersebut ditentukan pada lokasi pemanggilan.
- Ini membawa pertanyaan tambahan: apa yang harus menjadi perilaku ketika pengkompilasi mengalami skenario ini dengan referensi yang dikompilasi?
Menjawab
Kami akan pergi bersama 1.
Kesalahan aplikasi lebih lanjut (Dijawab)
Ada beberapa lokasi lagi seperti ini yang perlu dikonfirmasi. Mereka meliputi:
- Operator konversi - Spesifikasi tidak pernah mengatakan bahwa operator konversi melalui resolusi kelebihan beban, sehingga implementasi memblokir aplikasi pada anggota ini. Haruskah itu dikonfirmasi?
- Lambda - Demikian pula, lambda tidak pernah tunduk pada resolusi kelebihan beban, sehingga implementasi memblokirnya. Haruskah itu dikonfirmasi?
- Destruktor - sekali lagi, saat ini diblokir.
- Konstruktor statis - sekali lagi, saat ini sedang diblokir.
- Fungsi lokal - Ini saat ini tidak diblokir, karena melakukan mengalami resolusi kelebihan beban, Anda tidak dapat membebaninya secara berlebihan. Ini mirip dengan cara kami tidak melakukan kesalahan ketika atribut diterapkan ke anggota jenis yang tidak kelebihan beban. Haruskah perilaku ini dikonfirmasi?
Menjawab
Semua lokasi yang tercantum di atas diblokir.
Perilaku Langversion (Dijawab)
Implementasi saat ini hanya menimbulkan kesalahan versi bahasa ketika OverloadResolutionPriorityAttribute diterapkan, bukan atau ketika benar-benar memengaruhi sesuatu. Keputusan ini dibuat karena ada API-API tertentu yang akan ditambahkan oleh BCL (baik sekarang maupun di waktu mendatang) yang akan mulai menggunakan atribut ini; jika pengguna secara manual mengatur versi bahasa mereka kembali ke C# 12 atau sebelumnya, mereka mungkin akan melihat anggota-anggota API ini dan, tergantung pada perilaku langversion kami, akan:
- Jika kita mengabaikan atribut di C# <13, mengalami kesalahan ambiguitas karena API benar-benar ambigu tanpa atribut, atau;
- Jika kami melakukan kesalahan saat atribut memengaruhi hasil, menghadapi masalah bahwa API tidak dapat digunakan. Ini akan sangat buruk karena
Debug.Assert(bool)dikecilkan prioritasnya dalam .NET 9, atau. - Jika kita mengubah resolusi secara diam-diam, temui perilaku yang berpotensi berbeda antara versi kompilator yang berbeda jika seseorang memahami atribut dan yang lain tidak.
Perilaku terakhir dipilih, karena menghasilkan kompatibilitas yang paling maju, tetapi hasil yang berubah bisa mengejutkan beberapa pengguna. Haruskah kita mengonfirmasi ini, atau haruskah kita memilih salah satu opsi lainnya?
Menjawab
Kita akan menggunakan opsi 1, dengan diam-diam mengabaikan atribut dalam versi bahasa sebelumnya.
Alternatif
Proposal sebelumnya mencoba menentukan pendekatan BinaryCompatOnlyAttribute, yang sangat berat dalam menghapus hal-hal dari visibilitas. Namun, hal tersebut memiliki banyak masalah implementasi yang sulit yang berarti proposal tersebut terlalu kuat sehingga tidak berguna (mencegah pengujian API lama, misalnya) atau terlalu lemah sehingga tidak mencapai beberapa tujuan asli (seperti memiliki API yang jika tidak, akan dianggap ambigu ketika memanggil API baru). Versi tersebut direplikasi di bawah ini.
Usulan BinaryCompatOnlyAttribute (usang)
BinaryCompatOnlyAttribute
Desain terperinci
System.BinaryCompatOnlyAttribute
Kami memperkenalkan atribut cadangan baru:
namespace System;
// Excludes Assembly, GenericParameter, Module, Parameter, ReturnValue
[AttributeUsage(AttributeTargets.Class
| AttributeTargets.Constructor
| AttributeTargets.Delegate
| AttributeTargets.Enum
| AttributeTargets.Event
| AttributeTargets.Field
| AttributeTargets.Interface
| AttributeTargets.Method
| AttributeTargets.Property
| AttributeTargets.Struct,
AllowMultiple = false,
Inherited = false)]
public class BinaryCompatOnlyAttribute : Attribute {}
Ketika diterapkan ke anggota jenis, anggota tersebut diperlakukan sebagai tidak dapat diakses di setiap lokasi oleh pengkompilasi, yang berarti bahwa itu tidak berkontribusi pada pencarian anggota, resolusi kelebihan beban, atau proses serupa lainnya.
Domain Aksesibilitas
Kami memperbarui domain Aksesibilitas §7.5.3 sebagai mengikuti:
Domain aksesibilitas anggota terdiri dari bagian teks program (mungkin terputus-putus) di mana akses ke anggota diizinkan. Untuk tujuan menentukan domain aksesibilitas anggota, anggota dikatakan tingkat atas jika tidak dideklarasikan dalam tipe, dan anggota dikatakan terbenam jika dideklarasikan dalam tipe lain. Selain itu,teks programprogram didefinisikan sebagai semua teks yang terkandung dalam semua unit kompilasi program, dan teks program jenis didefinisikan sebagai semua teks yang terkandung dalam type_declarationjenis tersebut (termasuk, mungkin, jenis yang ditumpuk dalam jenis).
Domain aksesibilitas dari jenis yang telah ditentukan sebelumnya (seperti
object,int, ataudouble) tidak terbatas.Domain aksesibilitas dari jenis tidak terikat tingkat atas
T(§8.4.4) yang dideklarasikan dalam programPdidefinisikan sebagai berikut:
- Jika
Tditandai denganBinaryCompatOnlyAttribute, domain aksesibilitasTbenar-benar tidak dapat diakses oleh teks programPdan program apa pun yang mereferensikanP.- Jika aksesibilitas
Tyang dinyatakan bersifat publik, domain aksesibilitasTadalah teks programPdan program apa pun yang mereferensikanP.- Jika aksesibilitas
Tyang dinyatakan bersifat internal, domain aksesibilitasTadalah teks programP.Catatan: Dari definisi ini, dapat disimpulkan bahwa cakupan aksesibilitas dari tipe tingkat atas yang tidak terikat selalu setidaknya teks program dari program di mana tipe tersebut dideklarasikan. catatan akhir
Domain aksesibilitas untuk tipe terbangun
T<A₁, ..., Aₑ>adalah gabungan dari domain aksesibilitas tipe generik tak terikatTdan domain aksesibilitas dari argumen tipeA₁, ..., Aₑ.Domain aksesibilitas anggota bersarang
Myang dideklarasikan dalam tipeTpada programP, didefinisikan sebagai berikut (mencatat bahwaMitu sendiri mungkin merupakan tipe):
- Jika
Mditandai denganBinaryCompatOnlyAttribute, domain aksesibilitasMbenar-benar tidak dapat diakses oleh teks programPdan program apa pun yang mereferensikanP.- Jika aksesibilitas yang dinyatakan dari
Madalahpublic, maka domain aksesibilitasMadalah domain aksesibilitasT.- Jika aksesibilitas
Myang dinyatakan sebagaiprotected internal, anggaplahDsebagai penggabungan dari teks programPdan teks program dari jenis apa pun yang berasal dariT, yang dinyatakan di luarP. Domain aksesibilitasMadalah persimpangan domain aksesibilitasTdenganD.- Jika aksesibilitas
Madalahprivate protected, anggapDsebagai persimpangan dari teks programPdanTdan jenis apa pun yang berasal dariT. Domain aksesibilitasMadalah persimpangan domain aksesibilitasTdenganD.- Jika aksesibilitas
Mdinyatakan sebagaiprotected, makaDadalah gabungan teks programTdengan teks program dari setiap jenis yang diturunkan dariT. Domain aksesibilitasMadalah persimpangan domain aksesibilitasTdenganD.- Jika aksesibilitas
Mmerupakaninternal, maka domain aksesibilitasMadalah persimpangan antara domain aksesibilitasTdengan teks programP.- Jika aksesibilitas
Mdinyatakan sebagaiprivate, maka domain aksesibilitasMadalah teks program dariT.
Tujuan dari penambahan ini adalah untuk membuatnya sehingga anggota yang ditandai dengan BinaryCompatOnlyAttribute benar-benar tidak dapat diakses ke lokasi mana pun, mereka tidak akan berpartisipasi dalam pencarian anggota, dan tidak dapat memengaruhi sisa program. Akibatnya, ini berarti mereka tidak dapat menerapkan anggota antarmuka, mereka tidak dapat memanggil satu sama lain, dan mereka tidak dapat ditimpa (metode virtual), tersembunyi, atau diimplementasikan (anggota antarmuka). Apakah ini terlalu ketat adalah subjek dari beberapa pertanyaan terbuka di bawah ini.
Pertanyaan yang belum terselesaikan
Metode virtual dan penggantian
Apa yang kita lakukan ketika metode virtual ditandai sebagai BinaryCompatOnly? Penggantian dalam kelas turunan bahkan mungkin tidak termasuk dalam rakitan saat ini, dan bisa jadi pengguna ingin memperkenalkan versi baru metode yang, misalnya, hanya berbeda dengan jenis pengembalian, sesuatu yang biasanya tidak memungkinkan overload. Apa yang terjadi pada penimpaan metode sebelumnya saat kompilasi ulang? Apakah mereka diizinkan untuk mengambil alih anggota BinaryCompatOnly jika mereka juga ditandai sebagai BinaryCompatOnly?
Gunakan dalam DLL yang sama
Proposal ini menyatakan bahwa anggota BinaryCompatOnly tidak terlihat di mana pun, bahkan tidak di rakitan yang saat ini sedang dikompilasi. Apakah itu terlalu ketat, atau apakah anggota BinaryCompatAttribute mungkin perlu saling berantai satu sama lain?
Menerapkan anggota antarmuka secara implisit
Haruskah anggota BinaryCompatOnly dapat menerapkan anggota antarmuka? Atau harus mereka dicegah dari melakukannya. Ini akan mengharuskan bahwa, ketika pengguna ingin mengubah implementasi antarmuka implisit menjadi BinaryCompatOnly, mereka juga harus menyediakan implementasi antarmuka eksplisit, kemungkinan mengkloning isi yang sama dengan anggota BinaryCompatOnly karena implementasi antarmuka eksplisit tersebut tidak akan dapat melihat anggota asli lagi.
Menerapkan anggota antarmuka yang diberi tanda BinaryCompatOnly
Apa yang kita lakukan ketika anggota antarmuka telah ditandai sebagai BinaryCompatOnly? Tipe tersebut masih perlu memberikan implementasi untuk anggota tersebut; bisa jadi kita harus mengatakan bahwa anggota antarmuka tidak dapat ditandai sebagai BinaryCompatOnly.
C# feature specifications