I have a DLL that I'm making for Windows Forms applications. The layout looks a little something like this
public class A : UserControl
{
protected C c;
}
public class B : A { }
public class C { }
I want the DLL to only export class B, but it will not compile if I remove the public qualifier from A or C. Is there a way to do this?
Error from removing public from A:
Error CS0060 Inconsistent accessibility: base class 'A' is less accessible than class 'B'
From MSDN - Restrictions on Using Accessibility Levels (C# Reference):
When you specify a type in a declaration, check whether the accessibility level of the type is dependent on the accessibility level of a member or of another type. For example, the direct base class must be at least as accessible as the derived class.
Usually, in order to hide "stuff" from others, what you do, is provide a public interface and hide all the sub-classes. You can let your client create the concrete classes with a public factory which you will provide as well.
Not possible. If B inherits A, you simply cannot expose B without exposing A.
Related
Let's assume we have these two definitions
// assembly A
public abstract class A
{
internal abstract void func();
}
// assembly B
public class B : A
{
// internal override void func()
}
The error message says "B does not implement abstract member A.func()". I think that's bad design decision for reasons which I will try to describe in this post. I would be thankful for any insights for why the current design was chosen by creators of C# language. If I made internal members into Roslyn then I would surely create at least error saying something like "B cannot inherit from A which contains internal member" or ideally new keyword closed which forbids inheriting from another assembly without need of internal abstract member. Why? For these reasons:
a) Abstract class A may contain many members. Then I decide to inherit from class A in another assembly and after few days of work I implement most of its methods fixing one error by one. Then I suddenly see last error message saying that internal member is not implemented which IS NOT RECOVERABLE. This seems just wrong.
b) B is underlined although the problem is obviously that I am trying to inherit from A! Compiler should tell me that I am doing something wrong immediately without any of checking accessibility modifiers of every member in base class.
c) It is great that I can restrict inheriting from my base class from another assembly! But what if I want to restrict inheritance from my class which does not need any internal member? Then I am forced to add internal abstract member which is never used! I don't understand why people who created C# language just didn't make another keyword closed or whatever other name which would forbid inheritance from another assembly.
d) Adding internal member should not be breaking change outside of current assembly. I strongly believe in that. That's why if I designed C# I would prefer closed keyword. My feeling is that internal abstract members were not implemented properly.
Scenario:
I have 3 classes (A,B,C) in my Windows Runtime Component project.
class A{}
public sealed class B : A {}
public sealed class C : A {}
On compiling the above code, I get the following error:
"Inconsistent accessibility: base class 'A' is less accessible than
class 'C'."
If I make class A public, it gives a compile error :
"Exporting unsealed types is not supported. Please mark type
'MyProject.A' as sealed."
But now, if I make A as sealed, then B and C cannot inherit from it.
Considering the fact that only WinRT types are allowed for inheritance, is it anyhow possible to use custom/user-defined classes for inheritance? If not, is there any workaround to achieve the same?
As you've figured out by yourself, you can't expose classes that inherit from others in a Windows Runtime Component; that is true even if you try to use an abstract class as a parent class.
This is a "drawback" needed to make WinRT components works with all the others languages that the WinRT framework supports.
The only way to workaround this is avoiding inheritance.
You can only use interfaces or object composition where you can simulate inheritance behaviors, e.g.:
public sealed class A
{
public void Method() { }
}
public sealed class B
{
A a;
public void Method()
{
// Do B stuff
// Call fake "virtual" method
a.Method();
}
}
I have a class HierarchicalDictionary and some derived classes, for example Territory, Department, etc.
And I want to control that all classes that derive from HierarchicalDictionary contain property "Hierarchy" of type of that class (Territory, Department, etc.) during build. If it is not so I want build to fail.
That is if Territory doesn't contain property Hierarchy of type Territory or Department doesn't contain property Hierarchy of type Department, build should fail.
So I want that during compilation condition checked like that (pseudocode):
foreach (Class1 that derive from HierarchicalDictionary)
if(!(Class1 contains property Hierarchy of type Class1))
build fail
I thought about CodeContracts, but I don't know if there is availability to fail by condition during build.
May be there is some proper way?
UPD: I'll try to describe additional limitations for my situation:
HierarchicalDictionary is not stored (in database) class. And derived classes are stored, so corresponding tables contain self reference fields in database. When I derive class "C1" from HierarchicalDictionary I mean, that this class must contain property (or field) "Hierarchy" of type "C1" exactly. Like [ClassMustContainHierarchyFieldOfMyselfType] attribute. And I want to control that fact during compilation. If I have class "C2", that derives from HierarchicalDictionary and don't contain field (or property) "public C2 Hierarcy", build should fail.
May be there is no any "built-in" solutions. May be I can use pre- or post-build events or anything else (like CodeContracts for example)?
If HierarchicalDictionary can be abstract, you can define the property as abstract in the base class. This enforces a concrete implementation in every subclass.
If you need to be able to create instances of the base class HierarchicalDictionary you can enforce the property by adding an interface.
Well, may be you can do something like this:
// GENERIC base class
public abstract class A<T>
{
public abstract T GetMyType {get;}
}
//derived ones
public class B : A<B>
{
public override B GetMyType
{
get {
return new B();
}
}
}
public class C : A<C>
{
public override C GetMyType
{
get {
return new C();
}
}
}
and after in code:
new B().GetMyType.ToString(); //B
new C().GetMyType.ToString(); //C
So you create constrain with abstract method, plus every overriden method returns its own type, as they are derived from generic base class.
I do not understand the accessibility limitations exhibited below
public abstract class Base { }
internal class Common : Base { }
public class Instance : Common { }
This won't compile.
Inconsistent accessibility: base class 'Common' is less accessible than class 'Instance'
I can accomplish what I wanted with public abstract class Common but why can't I simply not expose the name at all?
Edit: What I'm asking is WHY it works this way! Everyone is answering with what the rules are, not explaining why the rules are that way.
Inheritors of a class cannot widen the scope of accessibility of the base class.
public: Access not limited
internal: Access limited to this program
Once limited to the program, all inheritors of a, internal class must remain internal or assume lesser accessibility (protected internal or private).
Per the C# specification, section §3.5.4 Accessibility constraints:
The parameter types of an instance constructor must be at least as
accessible as the instance constructor itself.
In the example
class A {...}
public class B: A {...}
the B class results in a compile-time error because A is not at least
as accessible as B.
Also:
The direct base class of a class type must be at least as accessible
as the class type itself (§3.5.2). For example, it is a compile-time
error for a public class to derive from a private or internal class.
If you are trying to create a Common class with functionality you prefer not to make accessible to external code, you should prefer composition over inheritance. For example:
public abstract class Base
{
...
}
internal class Common : Base
{
...
}
public class Instance
{
internal Instance(Common common)
{
...
}
...
}
It's a matter of how visible the code is to other assemblies. By making Common internal you're limiting access to Common to its assembly whereas by making Instance public you're making Instance accessible to any referencing assembly. If a referencing assembly can't access a type's base class how could it access any members inherited from that base class?
If Common contained a property, lets say Foo:
public string Foo { get; set; }
than the Instance class would automatically expose that property. You can think of it this way:
public void Test()
{
Common myInstance = new Instance();
System.Console.WriteLine(myInstance.Foo);
}
Since Instance needs to expose everything Common has, the access modifier on the base class cannot be less exposed.
You could, however, create the property Foo as internal to accomplish much the same.
I tried to make a class as private and got this Error "Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal"
I got its meaning but I want to ask why this is not allowed? Are all access modifires not applicable on Class? Why I can't make a class private, protected or protected internal?
Because private means that the member is only visible in the containing class. Since a top-level class has no class containing it it cannot be private (or protected).
(Internal or public are valid modifiers though).
What would you want private to mean on a top-level class?
Of course all modifiers apply to nested classes, i.e. a class defined within another class.
You can use only public or internal in the Namespace level
As Abatonime said, you can only use public or internal in the Namespace level.
private, protected, or protected internal can only be used in the Class level.
This works
namespace X
{
class A
{
// class code here
private class B // this class is an inner class
{
// class code here
}
}
}
This won't
namespace X
{
class A
{
// class code here
}
private class B // this is a class inside a namespace
{
// class code here
}
}
Because it doesn't make sense. There's no way you can access protected or private classes defined at namespace level, only as nested classes.
Only nested classes could be declared as private.
Not nested classes can be only public or internal (implicit without modifiers)
I had this same problem because I was creating a custom DLL and only wanted certain classes to be visible to an application using the DLL. So I just remove the modifier completely for classes I wanted to be private (within specific namespaces). The classes remained accessible to other classes within the same namespace in the DLL but did not show up in Intellisense in the calling application. No need for nested classes. The only explanation I can think of is the error message says cannot "explicitly" declare private...it doesn't say anything about implicitly.
namespace SmartCardAuthentication
{
class SmartCardIdentity : IIdentity
{
private string _firstName;
private string _lastName;
private string _middleInitial;
....
}
}
In example code above, class "SmartCardIdentity" is available to other class within same namespace, but not available to calling application when this class is rolled into a DLL. I have not tested it anyother way (i.e. visibility from a class in a different namespace within the DLL.).
The default accessibility of top-level types is internal.
The default accessibility of class and struct members is private.
The only possible accessibility of interface and enum members is public.
So a class is by default private, and if you want to access that, you have to put public before that.
Only Public and Internal are applicable when defining class. If no access modifier is defined before the class default is internal.
refer to MSDN - [https://msdn.microsoft.com/en-us/library/8fd16xs0(v=vs.90).aspx]
In real world we are focus on visible object
Once object is visible then we talk about scope of the object
example in real world
If you walking on street, you see houses in a colony
colony has houses.
If colony is protected no one can't able to see houses
It is consider that no colony no houses is present
In Programming
If we make class as private/ protected at top-level
no one known about it
is it present in assembly ?
please correct me, if i am out of the scope