2016-06-02 9 views
0

Hier ist ein vereinfachtes Beispiel, wie ich meinen Code arbeiten möchte. Bitte beachten Sie, dass dieser Code nicht kompiliert:C# Inkonsistente Zugänglichkeit Verhindert private Klassen als Parameter für geschützte Methoden

protected void doStuff(UtilityObject utilityObject) 

Uneinheitliche Zugänglichkeit:

namespace SpecificNamespace 
{ 
    class UtilityObject 
    { 
     //properties 
    } 

    public abstract class Entity 
    { 
     protected void doStuff(UtilityObject utilityObject) 
     { 
      //does stuff 
     } 
    } 

    // include implementations of Entity 
} 

namespace GeneralNamespace 
{ 
    public static class World 
    { 
     public static List<SpecificNamespace.Entity> Entities = new List<SpecificNamespace.Entity>(); 
    } 
} 

Es ist nicht wegen der Zeile nicht kompiliert Parametertyp ‚UtilityObject‘ ist weniger zugänglich als Methode ‚Entity .doStuff (UtilityObject utilityObject)‘

Aber ich schwöre, ich wollte nur Entity für Klassen implementieren, die innerhalb vondeklariert werdenund daher hätte jede Klasse, die auf die geschützte Methode Entity.Dostuff verweist, auch Zugriff auf UtillityObject. Da keine Klasse außerhalb dieses Namespace irgendwas weiß, was ein UtilityObject ist, möchte ich es nicht als öffentlich deklarieren. Auf der anderen Seite muss Entity öffentlich sein, so dass die Entitäten generisch bezeichnet werden können.

Gibt es einen Weg um dies? Ist das ein Mangel an C# -Konventionen? Bin ich damit gerade zu wertvoll?

+0

Randbemerkung: Ich bin ziemlich sicher, dass Sie falsche Vorstellung von Namensräumen haben - Namespaces in C# bedeuten absolut nichts zur Sichtbarkeit. Sie sind nur ein Teil des Typs name. Sie können alle Ihre Klassen im 'System'-Namespace deklarieren - aber dadurch werden ihnen keine magischen Kräfte verliehen. –

+0

Eine Klasse öffentlich zu machen, macht sie also nicht außerhalb ihres Namensraums sichtbar? –

+0

Wenn Sie es nur in Ihrer eigenen Assembly aufrufen, können Sie 'doStuff' intern anstatt geschützt machen. Das würde den Fehler beheben. –

Antwort

1

Versuchen Sie, UtilityObject zu einer inneren Klasse innerhalb der Entität mit geschütztem Zugriffswert zu machen.

+0

Kurz und prägnant. Vielen Dank. –

1

Wenn Sie UtilityObject in der Basisklasse Entity bewegt:

public abstract class Entity 
{ 
    class UtilityObject 
    { 
     //properties 
    } 

, dass ein Schritt näher ist; Allerdings muss UtilityObject mindestens geschützt sein, oder besser, weil es so aussieht: wenn public class A : Entity definiert ist, muss die Klasse A UtilityObject sehen können, und es kann nicht, wenn es privat ist (sogar privat innerhalb der Klasse) . Sie können in der Lage sein, protected class UtilityObject mit geschachtelten Klassen zu verwenden, aber nicht sicher; Wenn du kannst, wäre das näher ...

Aber das ist die Essenz warum du diesen Fehler bekommst; Alle zukünftigen Implementierungen müssen aufgrund des Umfangs hinzugefügt werden können.

0

Sie können eine öffentliche Schnittstelle machen IUtilityObject und dann können Sie Ihre UtilityObject Klasse halten interne wie haben Sie es:

namespace SpecificNamespace 
{ 
    public interface IUtilityObject 
    { 
     int Id { get; set; } 
    } 

    class UtilityObject : IUtilityObject 
    { 
     //properties 
     public int Id { get; set; } 
    } 

    public abstract class Entity 
    { 
     protected void doStuff(IUtilityObject utilityObject) 
     { 
      //does stuff 
     } 
    } 

    // include implementations of Entity 
} 
+0

oder ich könnte Entity privat machen und es eine öffentliche Schnittstelle implementieren. –

+0

@LorryLaurencemcLarry Ich glaube nicht, dass du Entity privat machen kannst, wo es gerade steht. Sie können eine Klasse nur dann als privat definieren, wenn sie in einer sichtbareren Klasse verschachtelt ist. –

+0

oh, also, was macht eine Klasse 'public', wenn sie nicht verschachtelt ist? –