Hoe kan ik een openbare eigenschap van de basisklasse verbergen in de afgeleide klasse

Ik wil de openbare basiseigenschap (een gegevenslid) in mijn afgeleide klasse verbergen:

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}
class a
{
    public int item1 {get; set;}
    public int item2 { get; set; }
}
class b : a
{
    new private int item1;
}
class c : a
{
}

ik heb lid als openbaar omdat ik wil dat het lid wordt overgenomen in c class , maar ik wil het lid in b class verbergen, hoe kan ik dit doen?

heb ik geen optie om de variabele die ik wil in mijn basisklasse selectief te erven ??? dat is echt slecht, ik denk dat ms ons een optie zou moeten bieden (kan een modificatie zijn) om dit uit te voeren


Bewerken:

Ik heb het antwoord zelf gevonden (ik heb velen van hen horen zeggen dat dit niet mogelijk is in c#, maar je kunt het wel)

Ik voeg de code toe voor het geval deze nuttig is

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4; // shows an error  : )
    }
}
class a
{
    public int item1 { get; set; }
    public int item2 { get; set; }
}
class b : a
{
    new public static int item1
    {
        get;
        private set;
    }
}

Antwoord 1, autoriteit 100%

Ik ga proberen met voorbeelden uit te leggen waarom dit een slecht idee is, in plaats van cryptische termen te gebruiken.

Uw voorstel zou zijn om een ​​code te hebben die er als volgt uitziet:

public class Base
{
    public int Item1 { get; set; }
    public int Item2 { get; set; }
}
public class WithHidden : Base
{
    hide Item1; // Assuming some new feature "hide" in C#
}
public class WithoutHidden : Base { }

Dit zou dan de volgende code ongeldig maken:

WithHidden a = new WithHidden();
a.Item1 = 10; // Invalid - cannot access property Item1
int i = a.Item1; // Invalid - cannot access property Item1

En dat zou precies zijn wat je wilde. Stel dat we nu de volgende code hebben:

Base withHidden = new WithHidden();
Base withoutHidden = new WithoutHidden();
SetItem1(withHidden);
SetItem1(withoutHidden);
public void SetItem1(Base base)
{
    base.Item1 = 10;
}

De compiler weet niet welk runtime-type de argumentbase in SetItem1 zal zijn, alleen dat het op zijn minst van het type Base is (of een type afgeleid van Base, maar het kan niet zeggen welke — het kan duidelijk zijn kijkend naar het codefragment, maar complexere scenario’s maken het praktisch onmogelijk).

Dus de compiler zal in een groot percentage van de gevallen geen compilerfout kunnen geven dat Item1 in feite ontoegankelijk is. Dus dat laat de mogelijkheid van een runtime-controle. Wanneer je Item1 probeert in te stellen op een object dat in feite van het type WithHidden is, zou er een uitzondering optreden.

Nu toegang tot een lid, elke eigenschap van een niet-verzegelde klasse (wat de meeste zijn) kan een uitzondering veroorzaken, omdat het in feite een afgeleide klasse was die het lid verborg. Elke bibliotheek die niet-verzegelde typen blootlegt, zou defensieve code moeten schrijven bij toegang tot elklid, alleen omdat iemand het mogelijk heeft verborgen.

Een mogelijke oplossing hiervoor is om de functie zo te schrijven dat alleen leden die zichzelf verbergbaar verklaren, verborgen kunnen worden. De compiler zou dan elke toegang tot het verborgen lid op variabelen van dat type (compileertijd) weigeren en ook runtime-controles opnemen zodat een FieldAccessException wordt gegenereerd als het naar het basistype wordt gecast en vanaf dat type wordt geprobeerd toegang te krijgen (runtime) .

Maar zelfs als de C#-ontwikkelaars de enorme moeite en kosten van deze functie hebben gedaan (onthoud dat functies duurzijn, vooral bij het ontwerpen van talen), moet er nog steeds defensieve code worden geschreven om de problemen te voorkomen van potentiële FieldAccessExceptions die worden gegooid, dus welk voordeel heeft u ten opzichte van het reorganiseren van uw overervingshiërarchie? Met de nieuwe functie voor het verbergen van leden zou er een enorm aantal potentiële plaatsen zijn waar bugs in uw applicatie en bibliotheken kunnen binnensluipen, waardoor de ontwikkelings- en testtijd toeneemt.


Antwoord 2, autoriteit 59%

Wat je wilt doen druist rechtstreeks in tegen OO, je kunt leden niet ‘depubliceren’ omdat dit in strijd is met het vervangingsprincipe. Je moet dit ombouwen tot iets anders.


Antwoord 3, autoriteit 26%

De reactie van Vadim deed me denken aan hoe MS dit op bepaalde plaatsen in het Framework bereikt. De algemene strategie is om het lid te verbergen voor Intellisense met behulp van het EditorBrowsable-kenmerk. (NB Dit verbergt het alleen als het zich in een andere assembly bevindt) Hoewel het niemand ervan weerhoudt het attribuut te gebruiken, en ze het kunnen zien als ze naar het basistype casten (zie mijn vorige uitleg), maakt het het veel minder vindbaar omdat het verschijnt niet in Intellisense en houdt de interface van de klas schoon.

Het moet echter met mate worden gebruikt, alleen wanneer andere opties, zoals het herstructureren van de overervingshiërarchie, het veelingewikkelder zouden maken. Het is een laatste redmiddel in plaats van de eerste oplossing om aan te denken.


Antwoord 4, autoriteit 19%

Als u een interface gebruikt in plaats van een basisklasse voor het definiëren van de eigenschap, kunt u de eigenschap expliciet implementeren. Het zou een expliciete cast naar de interface vereisen om de eigenschap te gebruiken.

public interface IMyInterface
{
    string Name { get; set; }
}
public class MyClass : IMyInterface
{
    string IMyInterface.Name { get; set; }
}

Je kunt hiermeer informatie vinden.


Antwoord 5, autoriteit 15%

Het enige wat ik kan bedenken is om item1 virtueel te maken in klas a:

class a
{
    public virtual int item1 { get; set; }
    public int item2 { get; set; }
}

en overschrijf het dan in klasse b, maar gooi een uitzondering in getter en setter. Ook als deze eigenschap wordt gebruikt in een visuele ontwerper, kunt u Browsable gebruiken attribuutom niet weer te geven.

class b : a
{
    [Browsable(false)]
    public override int item1
    {
        get
        {
            throw new NotSupportedException();
        }
        set
        {
            throw new NotSupportedException();
        }
    }
}

Antwoord 6, autoriteit 4%

Allereerst is dit geen goed idee als je bepaalde methoden gebruikt die de basisklasse gebruiken.
Je kunt proberen om verouderde argumenten te gebruiken om gebruikers te laten nadenken over het gebruik van deze eigenschap.

[System.Obsolete("Do not use this property",true)]  
public override YourType YourProperty { get; set; }

Antwoord 7

Wat u beschrijft, lijkt op ‘private overerving’ uit C++ en is niet beschikbaar in C#.


Antwoord 8

U kunt het niet rechtstreeks doen, maar u kunt de eigenschappen in de onderliggende klasse overschrijven en ze alleen-lezen maken, bijvoorbeeld

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}
class a
{
    public virtual int item1 {get; set;}
    public virtual int item2 { get; set; }
}
class b : a
{
    public override int item1
    { 
         get { return base.item1; }
         set { }
    }
}
    class c : a
{
}

Antwoord 9

U kunt interfaces gebruiken om de eigenschap te verbergen. De onderliggende klasse zou een interface implementeren die de eigenschap niet had, dan zou deze niet verschijnen.

Je hebt twee interfaces nodig voor wanneer je het eigendom wilt en wanneer niet, waardoor het een vreselijke hack wordt.


Antwoord 10

Je kunt het overschrijven en vervolgens een [Browsable(false)]-tag toevoegen om te voorkomen dat het in designer wordt weergegeven.

Eenvoudig:

public class a:TextBox
{
        [Browsable(false)]
        public override string Text
        {
            get { return ""; }
            set { }
        }
}

Antwoord 11

Het wijzigen van de toegankelijkheid van een virtueel lid is een overervende klasse is specifiek verboden door de C#-taalspecificatie:

De overschrijfdeclaratie en de overschreven basismethode hebben hetzelfde
verklaarde toegankelijkheid. Met andere woorden, een override-declaratie kan niet
de toegankelijkheid van de virtuele methode wijzigen.
Echter, als de
overschreven basismethode is intern beveiligd en wordt gedeclareerd in a
andere assembly dan de assembly die de override-methode bevat
dan moet de verklaarde toegankelijkheid van de override-methode worden beschermd.

Van sectie 10.6.4 Overschrijfmethoden

Dezelfde regels die van toepassing zijn op overschrijvende methoden zijn ook van toepassing op eigenschappen, dus van publicnaar privategaan door over te nemen van de basisklasse kan niet worden gedaan in C#.


Antwoord 12

Wat je eigenlijk nodig hebt, zijn interfaces:

   public interface ProvidesItem1
    {
        int item1 { get; set; }
    }
    public interface ProvidesItem2
    {
        int item2 { get; set; }
    }
    class a : ProvidesItem1, ProvidesItem2
    {
        public int item1 { get; set; }
        public int item2 { get; set; }
    }
    class b : ProvidesItem1
    {
        public int item1 { get; set; }
    }

Laat de interfaces dan gewoon rondgaan. Als de klassen een gemeenschappelijke implementatie zouden moeten gebruiken, plaats die dan in een derde klasse en laat ze uit die klasse voortkomen en hun respectieve interface implementeren.


Antwoord 13

Ja, dat is mogelijk. Wat zegt u over de delegatie. Ik zal proberen een idee te geven van wat in OOP “delegatie” wordt genoemd met een stukje code:

public class ClassA
{
    // public
    public virtual int MyProperty { get; set; }
    // protected
    protected virtual int MyProperty2 { get; set; }
}
public class ClassB
{
    protected ClassC MyClassC;
    public ClassB()
    {
        MyClassC = new ClassC();
    }
    protected int MyProperty2
    {
        get { return MyClassC.MyProperty2; }
        set { MyClassC.MyProperty2 = value; }
    }
    protected int MyProperty
    {
        get { return MyClassC.MyProperty; }
        set { MyClassC.MyProperty = value; }
    }
    protected class ClassC : ClassA
    {
        public new int MyProperty2
        {
            get { return base.MyProperty2; }
            set { base.MyProperty2 = value; }
        }
        public override int MyProperty
        {
            get { return base.MyProperty; }
            set { base.MyProperty = value; }
        }
    }
}

Antwoord 14

namespace PropertyTest    
{    
    class a
    {    
        int nVal;
        public virtual int PropVal
        {
            get
            {
                return nVal;
            }
            set
            {
                nVal = value;
            }
        }
    }
    class b : a
    {
        public new int PropVal
        {
            get
            {
                return base.PropVal;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            a objA = new a();
            objA.PropVal = 1;
            Console.WriteLine(objA.PropVal);
            b objB = new b();
            objB.PropVal = 10; // ERROR! Can't set PropVal using B class obj. 
            Console.Read();
        }
    }
}

Antwoord 15

Als u een lid van de basisklasse wilt verbergen, moet u een nieuwe basisklasse toevoegen, laten we het bellen en moet uw code als volgt zijn:

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}
class baseA
{
    public int item2 { get; set; }
}
class a:baseA
{
    public int item1 { get; set; }        
}
class b : baseA { }
class c : a { }

Antwoord 16

U kunt de gebruiker newMODIFER.

monster;

public class Duck
{
    public string Color{get; set;}
    public void Swim() { }
}
public class DonaldDuck : Duck
{
    new public void Swim() 
    { 
        /*you could call in DonaldDuck.Swim  only here but not public for DonaldDuck client.*/ 
    }
}

Other episodes