views:

316

answers:

7

In C# Is there way to specify a class to be inherited only by a class present in the same assembly and for other assemblies should behave like a public sealed type.

A: 

No. There is no such provision in the C# language itself. However, workarounds -- as suggested by others here -- may suffice.

Frederick
voted up, it may not be helpful but it is correct
Oliver N.
It is technically correct, but I suspect that Ramesh probably already intuited that. It's more helpful to provide potential workarounds.
Michael Meadows
-1, votes are for being helpful, not just correct.
Samuel
+1, technically it is a right answer. Right answers can remain 0 but not in negative is my opinion.
Ramesh
+6  A: 

The language itself doesn't have anything that makes this easy, but you should be able to do this by making your constructors internal. If you do this, however, you won't be able to new it up from external assemblies, so you'll have to add a factory method.

public class Foo
{
    internal Foo()
    {
    }

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

Here's an alternative that lets you new up the class in external assemblies

public sealed class Foo : FooBase
{

}

public class FooBase
{
    internal FooBase() { }
}

One question you might ask yourself, however, is exactly why you want the class to be sealed. Sometimes it's inevitable, but I have seen the sealed keyword get abused so often that I thought I'd bring it up. Often, developers will seal classes because they are overprotective of their code. Most of the time, if a class is well designed, it doesn't need to be sealed.

Michael Meadows
I don't know why this was downvoted. IMO, it is the most correct answer posted.
Marc Gravell
+1 - For your thoughts. But the problem is I need it for ConfigurationElementCollection so, I don't think constructor cannot be made internal in my case
Ramesh
Try the second solution, create a base class that has internal constructors, and then implement it with a sealed class that has public constructors.
Michael Meadows
+1  A: 

If your class is abstract, there's a very simple way to do it:

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

Now although your class and most members are public, the internal abstract member makes it impossible to derive from the class outside your assembly.

Andrew Arnott
+1  A: 

You can't do that with language constructs, but try with reflection

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

Checked it up. Seems to be working. The only problem is that unless somebody reads documentation, the trouble is known at runtime.

It would be nice if you could flag it with some sort of attribute, like you do with obsolete code.
Michael Meadows
Well, you can always add to <summary> comment: "This class cannot be inherited."
+1  A: 

The only way I can think would be to use a public wrapper on an internal class, probably with a common interface:

public interface IFoo
{
}

internal class Foo : IFoo
{
}

public sealed class PublicFoo : IFoo
{
    private Foo m_Foo = new Foo();
}
Chris Shaffer
+6  A: 

I think Eric Lippert gets the defining quotes here:

Marc Gravell
+1 that was an informative read. Occasionally, I come across a blog that affects my way of thinking permenantely. These were two that did that.
Michael Meadows
A: 
public abstract class Foo
{
  protected internal Foo()
  {
  }

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