2009-03-10 7 views
10

In C# Gibt es eine Möglichkeit, eine Klasse anzugeben, die nur von einer Klasse geerbt wird, die in derselben Assembly vorhanden ist, und sich für andere Assemblys wie ein öffentlicher versiegelter Typ verhält.Inheritable nur innerhalb der Assembly in C#

Antwort

0

Nein. In der C# -Sprache gibt es keine solche Bestimmung. Allerdings können Umgehungslösungen - wie von anderen hier vorgeschlagen - ausreichen.

+0

abgestimmt auf, kann es nicht hilfreich sein, aber es ist richtig –

+0

Es ist technisch korrekt, aber ich vermute, dass Ramesh wahrscheinlich schon angeschaut Das. Es ist hilfreich, potenzielle Problemumgehungen bereitzustellen. –

+0

-1, Stimmen sind hilfreich, nicht nur korrekt. – Samuel

13

Die Sprache selbst hat nichts, was dies einfach macht, aber Sie sollten dies tun können, indem Sie Ihre Konstruktoren intern machen. Wenn Sie dies jedoch tun, können Sie es nicht von externen Assemblys neu erstellen, daher müssen Sie eine Factory-Methode hinzufügen.

public class Foo 
{ 
    internal Foo() 
    { 
    } 

    public Foo Create() 
    { 
     return new Foo(); 
    } 
} 

Hier ist eine Alternative, die Sie neu, um die Klasse in externen Baugruppen

public sealed class Foo : FooBase 
{ 

} 

public class FooBase 
{ 
    internal FooBase() { } 
} 

Eine Frage, können Sie sich vielleicht fragen, ist jedoch genau warum Sie die Klasse wollen versiegelt werden. Manchmal ist es unvermeidlich, aber ich habe gesehen, dass das Stichwort sealed so oft missbraucht wurde, dass ich dachte, ich würde es aufbringen. Oft schließen Entwickler Klassen ab, weil sie ihren Code zu sehr schützen. Die meiste Zeit, wenn eine Klasse gut entworfen ist, muss sie nicht versiegelt werden.

+1

Ich weiß nicht, warum das abgelehnt wurde. IMO, es ist die richtige Antwort geschrieben. –

+0

+1 - Für Ihre Gedanken. Aber das Problem ist, ich brauche es für ConfigurationElementCollection so, ich glaube nicht, Konstruktor kann nicht in meinem Fall intern gemacht werden – Ramesh

+0

Probieren Sie die zweite Lösung, erstellen Sie eine Basisklasse, die interne Konstruktoren hat, und implementieren Sie es dann mit einer versiegelten Klasse, die öffentlich hat Konstruktoren. –

4

Wenn Ihre Klasse abstrakt ist, gibt es eine sehr einfache Art und Weise, es zu tun:

public abstract class Foo { 
    internal abstract void DoNothing(); 
    // ... other members 
} 

Nun, obwohl die Klasse und die meisten Mitglieder der Öffentlichkeit sind, das interne abstrakte Mitglied macht es unmöglich, aus der Klasse abzuleiten außerhalb Versammlung.

+0

Ich würde vorschlagen, die Methode 'PreventExternalInheritance' oder etwas ähnliches zu nennen. –

1

Sie nicht, dass mit Sprachkonstrukte tun, sondern versuchen, mit Reflexion

public class MyClass{ 
    public MyClass(){ 
    if(this.GetType().Assembly != typeof(MyClass).Assembly){ 
     throw new Exception("Can't derive from this type!"); 
    } 
} 

Karo es auf. Scheint zu arbeiten. Das einzige Problem ist, dass, wenn jemand Dokumentation liest, das Problem zur Laufzeit bekannt ist.

+0

Es wäre nett, wenn Sie es mit einer Art Attribut kennzeichnen könnten, wie Sie mit veraltetem Code tun. –

+0

Nun, Sie können immer hinzufügen,

Kommentar: "Diese Klasse kann nicht vererbt werden." – user76035

1

Die einzige Möglichkeit, die ich denken kann würde eine öffentliche Wrapper auf eine interne Klasse zu verwenden, wahrscheinlich mit einer gemeinsamen Schnittstelle:

public interface IFoo 
{ 
} 

internal class Foo : IFoo 
{ 
} 

public sealed class PublicFoo : IFoo 
{ 
    private Foo m_Foo = new Foo(); 
} 
1

I Ich weiß, das ist ein alter Post, aber ich habe einen anderen Weg gefunden, der wirklich gut funktioniert, und ich wollte ihn für andere Leute veröffentlichen.

  1. Erstellen Sie eine Basisklasse mit einem internen Konstruktor.
  2. Lassen Sie Ihre abgeleiteten Klassen von der Basisklasse erben und versiegeln.

`` ``

public abstract class LockResult { 
    internal LockResult() { 

    } 
} 

public sealed class LockSucceededResult : LockResult { 
    //Info for when a lock succeeded 
} 

public sealed class LockFailedResult : LockResult { 
    //Info for when a lock failed 
} 

`` ``

+0

@Michael Antwort (https://StackOverflow.com/a/630308/30594) bietet die gleiche Lösung – Ramesh