According to object oriented principles, we can define any class in any namespace as private or protected but when I create a class as private or protected I get the following compilation error:
Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal
namespace test
{
public class A
{
public A()
{
}
}
protected class B //throwing error
{
}
}
I searched for a solution and I found the following on Stack Overflow:
Anything that is not a member of an enclosing type (class) doesn't make sense at all to be protected.
Why can't I declare B as protected?
I guess I don't understand what protected means. What does it mean?
Only nested classes can be marked as protected.
namespace test
{
public class A
{
public A() { }
protected class B
{
public B() { }
}
}
}
Protected says that the class can only be used inside the class it is specified in or inherited from. Therefore it does not make sense to declare a protected class in a namespace. What would this mean? Protected can only be applied to nested classes therefore.
In C# you cannot declare classes as protected, except when they are nested within other classes:
namespace test
{
public class A
{
public A()
{
}
protected class B // nested class
{
}
}
}
This makes sense because protected means that it should only be accessible by the enclosing class or a class derived from that enclosing class.
If it is ok if class B can be accessed by all classes in the same assembly but not from outside, you can declare the class as internal:
namespace test
{
public class A
{
public A()
{
}
}
internal class B // accessible within same assembly
{
}
}
Related
This question already has answers here:
When and why would you seal a class?
(5 answers)
Closed 2 years ago.
I know that you can not inherit from a class once sealed is used but I am confused what is the difference between these two: private and sealed?
Can't we make the base class members private if we don't want to inherit them instead of the whole class? What is the point of using sealed class?
private: private limits the visiblity to a scope. Declaring a private class within a class means that sub-class can't be seen from outside of the class.
This is also true for methods and properties - they can be seen within the class, but not to any consumers or inheritors.
private keyword is used for declaring class.
sealed: If a class is declared as sealed, that means that you cannot inherit from the class. sealed class can be used when a class is internal to the operation of the library, class or why you do not want that class to be overridden because it may affect the functionality.
sealed keyword is used for declaring class
example
public class Parent {
// some thing at here
private readonly SubClass sc;
// ctor
public Parent () {
sc = new SubClass();
}
public string foo () {
return sc.bar();
}
private class SubClass {
// have some thing here
public string bar() {
//..............
return "...........";
}
}
}
You need to understand difference between inheritability and accessibility.
If you want to make your class non-inheritable, making it sealed is the best option. Also a class can not be protected, private or internal protected. Only sub class can have those access specifiers. A normal class which is directly under a namespace can only be public or internal.
Now coming to you point of making all the members private in the base class. Doing that does not serve any purpose.
You inherit a class only to reuse certain properties and/or method or override them in the inherited class. If you make all the members private in the base class you won't be able access them outside even using the object of base class.
Then what's the point of having them in the base class.
public class MyClass
{
private void MyMethod() //You can not inherit this method but you can not use it using 'MyClass' also.
{
//Some code.
}
}
MyClass myObj = new MyClass();
myObj.MyMethod(); // You can not do this as the method is private.
Now if you inherit this class in another class
public ChildClass : MyClass
{
public void ChildMethod()
{
// Some Logic
}
}
Now when you do
MyClass obj = new ChildClass();
You can not do
obj.MyMethod(); //coz this is private method.
You can not do following too.
obj.ChildMethod(); //coz that method is not known to MyClass.
So if you are making members private just for the sake of making them not available for inheritance, you are losing their accessibility from the base class too.
Understood your confusion,
First of all there is no independent private class inside a namespace, compiler throws an error.
If you make a method void m1() private inside public class A, then the method m1 is not accessible from public class B.
Sealed classes are accessible to other classes though it stops inheritance, meaning you cannot use it to derive from.
In the example below, you wont be able to access the method privatemethod from the Main(), but sealed class and sealed method can be accessed. So sealed can be accessed though cannot be inherited, that's the difference.
namespace ConsoleApp1
{
using System;
public class A
{
public virtual void test()
{
Console.WriteLine("Class A");
}
}
public class C
{
public void testSealFromOutsideClass()
{
B instanceB = new B();
instanceB.test();
}
}
public sealed class B : A
{
public override void test()
{
Console.WriteLine("Class B");
}
private void Privatemethod()
{
Console.WriteLine("Printing from a private method");
}
}
//public class C : B {}
public class TestSealedClass
{
public static void Main()
{
A a = new B();
a.test();
C c = new C();
c.testSealFromOutsideClass();
B b = new B();
Console.Read();
}
}
}
This question already has answers here:
How to make a property protected AND internal in C#?
(8 answers)
Closed 7 years ago.
Consider the following classes:
public class Vehicle { ... }
public class Coverage { ... }
public class VehicleList : IEnumerable<Vehicle> { ... }
public class CoverageList : IEnumerable<Coverage> { ... }
public abstract class Quote
{
protected VehicleList vehicles;
protected CoverageList coverages;
internal Quote() { ... }
public IReadOnlyCollection<Vehicle> Vehicles
{
get { return this.vehicles.AsReadOnly(); }
}
public IReadOnlyCollection<Coverage> Coverages
{
get { return this.coverages.AsReadOnly(); }
}
...
}
public sealed class OhQuote : Quote
{
//needs to access protected fields
...
}
public sealed class InQuote : Quote { ... }
public sealed class MiQuote : Quote { ... }
Quote fully encapsulates the functionality of both VehicleList and CoverageList so I'd like to mark those classes as internal. The problem is that they are the types of protected fields of a public class. If I mark those fields as protected internal then they are protected OR internal. What I really need is for them to be protected AND internal (with protected taking precedence within the assembly). You can see that neither Quote (which has an internal constructor) nor its subclasses (which are sealed) can be extended outside the assembly. I've already figured out how to achieve the desired functionality using public interfaces but wanted to make sure there's not a more concise way.
Although the .NET runtime supports this concept ("FamilyAndAssembly"), C# currently does not.
This was proposed for C# 6.0 in the form of the private protected access modifier, but the feature was dropped.
UPDATE: private protected was added to C# 7.2.
As an addendum:
If you want not to use interfaces and -as you see- there is no C# support to achieve that goal, remember: you can always use reflection to do very weird and strange things like that.
You can set the field to private and using reflection you can assign new values from wherever you want, for sure from derived classes in same assembly.
I question the need for your derived classes to access Quote's fields directly.
I am asking if there is a way to achieve the desired functionality without using public interfaces.
I think you can safely change the modifiers on the fields to private and have the derived classes manipulate the fields indirectly through protected methods defined in your Quote base class. No additional public interfaces would be required.
Here is an example of what it could look like:
public class Vehicle {}
public class Coverage {}
// Set these as "internal" as you were hoping for...
internal class VehicleList : IEnumerable<Vehicle>
{
public void Foo() {}
}
internal class CoverageList : IEnumerable<Coverage>
{
public void Bar() {}
}
public abstract class Quote
{
// Mark these as "private"
private VehicleList vehicles;
private CoverageList coverages;
internal Quote() {}
public IReadOnlyCollection<Vehicle> Vehicles
{
get { return this.vehicles.AsReadOnly(); }
}
public IReadOnlyCollection<Coverage> Coverages
{
get { return this.coverages.AsReadOnly(); }
}
// Add protected methods to manipulate the private fields.
protected void PerformFooOnVehicles()
{
this.vehicles.Foo();
}
protected void PerformBarOnCoverages()
{
this.coverages.Bar();
}
}
public sealed class OhQuote : Quote
{
// We now have indirect access to Quote's private fields.
public void Baz()
{
this.PerformBarOnCoverages();
this.PerformFooOnVehicles();
}
}
public sealed class InQuote : Quote {}
public sealed class MiQuote : Quote {}
This alternative accomplishes the goal of indirectly exposing VehicleList and CoverageList only to derived classes that are part of the same assembly.
using System.IO;
using System;
using Assembly2;
// DLL 1
namespace Assembly1
{
class class1 : class2
{
static void Main()
{
Console.WriteLine(new class2().sample); //Cannot access. Protected means --> accessible to the derived classes right ? (But, note that this is a different assembly. Does not work because of that ?)
}
}
}
// DLL 2
namespace Assembly2
{
public class class2
{
protected string sample = "Test";
}
}
In the above simple code,
I cannot access the string sample in assembly 2 though I am deriving from class2
From MSDN:
The type or member can be accessed only by code in the same class or struct, or in a class that is derived from that class.
Does this definition stand only for the same assembly or can the protected members be accessed across assemblies ?
You can access the protected member from a different assembly, but only within a subclass (as normal for protected access):
// In DLL 1
public class Class3 : class2
{
public void ShowSample()
{
Console.WriteLine(sample);
}
}
Note that your current code would fail even if the classes were in the same assembly.
A protected member of a base class is accessible in a derived class only if the access occurs through the derived class type.
class class1:class2
{
static void Main()
{
Console.WriteLine(new class1().sample);
}
}
now above code will run.
I have a class like this:
public class Base
{
public Base(string name)
{
this.Name = name;
}
public string Name { get; set; }
public string PrettyName
{
get { return Prettify(Name); }
}
}
and I derive from it:
public class Derived : Base
{
public Derived(Base b) : base(b.Name) { }
}
The Name property should not be accessed; the logical name should be accessed only by PrettyName. So I thought I'd make the property like this:
public string Name { protected get; set; }
But I'm getting this:
Cannot access protected member 'Name' via a qualifier of type 'Base'; the qualifier must be of type 'Derived' (or derived from it)
Why is that? The getter should be exposed to the base class and all its child classes. Am I getting something wrong here?
The getter should be exposed to the base class and all its child classes.
No, not quite. This isn't a matter of automatically implemented properties - it's a matter of what protected means.
Access to a protected member within a subclass has to be through an instance of that subclass (or a further subclass). You can't use Base.Name for an arbitrary Base in Derived.
From section 3.5.3 of the C# spec:
When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class.
A simple solution would be to overload the constructor in Base:
protected Base(Base b) : this(b.Name)
{
}
then in Derived:
public Derived(Base b) : base(b) { }
At that point, you can make the Name setter private, too - or better yet, make it fully read-only:
private readonly string name;
public string Name { get { return name; } }
That's a curious way of making the derived constructor. Why not:
public class Derived : Base
{
public Derived(string name) : base(name)
{ }
public void Test()
{
//here, it's perfectly ok to access the protected Name.
}
}
I have an internal class
namespace commonNamespace
{
internal class A{}
}
i have another public class within the same assembly
public class B{}
I want to declare an array of type A in classB.
ex:
namespace commonNamespace
{
public class B
{
A[] array;
}
}
I am getting inconsistent accessibility Level error message.Please let me know how can i do this.
You must have a public/protected field or property in B exposing some instance(s) of type A. Mark that as internal and you should be good to go.
Just add access modifier to the field Array:
public class B
{
internal A[] array;
}
This is the Access Modifiers hierarchy:
public > protected > internal > internal protected > private
So just choose anything below protected and you will be fine.