Pertanyaan Apakah ada cara untuk mencapai anggota `protected` dari objek lain dari tipe turunan?


class MyBase
{
    protected object PropertyOfBase { get; set; }
}

class MyType : MyBase
{
    void MyMethod(MyBase parameter)
    {
        // I am looking for:
        object p = parameter.PropertyOfBase;  // error CS1540: Cannot access protected member 'MyBase.PropertyOfBase' via a qualifier of type 'MyBase'; the qualifier must be of type 'MyType' (or derived from it)
    }
}

Apakah ada cara untuk mendapatkan properti yang dilindungi dari parameter tipe dari tipe yang diperluas tanpa refleksi? Karena kelas yang diperluas mengetahui properti melalui jenis dasarnya, akan masuk akal jika memungkinkan.


12
2017-12-05 16:58


asal


Jawaban:


Tidak, kamu tidak bisa melakukan ini.

Anda hanya diperbolehkan mengakses anggota objek yang dilindungi dari jenis pengaksesan (atau berasal darinya). Di sini, kita tidak tahu apakah parameter adalah tipe MyType atau SomeOtherCompletelyDifferentType.

EDIT: Bit yang relevan dari spesifikasi C # 3.0 adalah bagian 3.5.3:

Ketika anggota instan yang dilindungi adalah   diakses di luar teks program   kelas yang dideklarasikan, dan   saat instance internal yang dilindungi   anggota diakses di luar program   teks program di mana itu   menyatakan, akses harus dilakukan   dalam deklarasi kelas itu   berasal dari kelas di mana itu   dideklarasikan. Selanjutnya, aksesnya   diperlukan untuk mengambil tempat melalui suatu   contoh dari tipe kelas turunan atau   jenis kelas yang dibangun darinya. Ini   pembatasan mencegah satu kelas turunan   dari mengakses anggota dilindungi dari   kelas turunan lainnya, bahkan ketika   anggota diwariskan dari yang sama   kelas dasar.


11
2017-12-05 17:14



Terakhir kali saya menghadapi masalah yang sama, saya menggunakan solusi penambahan metode statis yang terlindungi ke basis:

class MyBase
{
    protected object PropertyOfBase { get; set; }

    protected static object GetPropertyOfBaseOf(MyBase obj) 
    {
        return obj.PropertyOfBase;
    }
}

class MyType : MyBase
{
    void MyMethod(MyBase parameter)
    {
        object p = GetPropertyOfBaseOf(parameter);
    }
}

15
2018-06-14 08:01



Ada alasan bagus kamu tidak bisa melakukan ini. Misalkan seseorang menulis:

class Other : MyBase { }

new MyType().MyMethod(new Other());

Jika bahasa memungkinkan apa yang Anda minta, Anda bisa melanggar invariants yang diasumsikan Other dengan memodifikasi nilai PropertyOfBase.


5
2017-12-05 17:58



Saya pikir Anda harus bertanya pada diri sendiri apakah ada cara yang lebih baik untuk melakukan apa yang ingin Anda lakukan. Anda ingin PropertyOfBase bertindak sebagai publik dalam konteks MyType.MyMethod (), tetapi harus dilindungi dalam semua situasi lainnya. Mengapa?


2
2017-12-05 17:59



Properti yang dilindungi hanya dapat diakses oleh turunan kelas turunan, bukan ke instance kelas turunan.

Ada perbedaan dan itu masuk akal, anggota yang dilindungi tidak boleh menyerahkan nilainya ke contoh lain, bahkan turunan yang berasal dari jenis yang sama.

(Diedit, membuat lidahku sedikit terikat!)


1
2017-12-05 17:19



Ketika Anda mewarisi dari MyBase, Anda dapat mengakses semua bidang / properti / metode dari itu ditandai sebagai "dilindungi" menggunakan kata kunci "dasar".

public class MyBase
{
    protected object PropertyOfBase { get; set; }
}

public class MyType : MyBase
{
    void MyMethod()
    {
        object p =  base.PropertyOfBase;
    }
}

0
2018-03-01 22:57



Anda juga dapat mendeklarasikan MyType sebagai kelas bersarang dari MyBase (alih-alih mewarisi), dengan cara ini Anda dapat mengakses anggota pribadi / dilindungi saat Anda mengirim kelas MyBase sebagai parameter

public class MyBase
{
    protected object PropertyOfBase { get; set; }

    public class MyType
    {
        public void MyMethod(MyBase parameter)
        {
            object p = parameter.PropertyOfBase;  
        }
    }
}

Untuk membuat instance dari MyType, gunakan saja

var t = new MyBase.MyType();
t.MyMethod(new MyBase());

0
2018-03-06 20:37