what is internal protection, and why does strange class work? - c#

If I make BaseClass public it starts complaining:
Assets/TestScript.cs(14,14): error CS0060: Inconsistent accessibility: base class `Class1' is less accessible than class `BaseClass'
First I don't understand why is it complaining as afaik base class should be the one from where you start accessing stuff
B cannot access protected functions witch is fine.
but what are the internal classes?
using UnityEngine;
using System.Collections;
public class TestScript : MonoBehaviour {
BaseClass B = new BaseClass();
Class2 A = new BaseClass(); // how can this even work and why does it work?
Class2 C = new Class2(); // Assets/TestScript.cs(7,28): error CS0144: Cannot create an instance of the abstract class or interface `Class2' // - WTH why?
void Start(){
B.BaseFunction(); // Base
B.Function1(); // Assets/TestScript.cs(10,19): error CS0122: `Class1.Function1()' is inaccessible due to its protection level
A.Function2(); // 2
}
}
internal class BaseClass : Class1 {
internal void BaseFunction(){
Debug.Log("Base");
}
}
internal abstract class Class1 : Class2{
protected void Function1(){
Debug.Log("1");
}
}
public abstract class Class2{
public void Function2(){
Debug.Log("2");
}
}
or did I just make bunch of stuff that works same as public does?
but ATM what bugges me the most is why does this work:
Class2 A = new BaseClass();
if this doesn't work
Class2 C = new Class2();
Sorry if I'm too little knowledgeable about classes I just started learning them today after 1 year of programming.

You have everything named very badly... it makes it confusing. If you make BaseClass actually be a base class.. then it should make more sense:
public abstract class AbstractBase {
public void BaseFunction(){
Debug.Log("2");
}
}
public class Class1 : AbstractBase {
public void ClassOneFunction(){
Debug.Log("Base");
}
}
public abstract class Class2 : Class1 {
public void ClassTwoFunction(){
Debug.Log("1");
}
}
Now if we re-work your issues, you get something like this:
AbstractBase A = new Class1();
You are representing an instance of Class1 as an AbstractBase which is totally fine. You can substitute anything that inherits from AbstractBase in place of an AbstractBase declaration. This is polymorphism at work.
The key thing to remember here is that when you represent an instance of Class1 as an AbstractBase.. it is only "visible" as an AbstractBase. So, given the above code.. this won't work:
AbstractBase A = new Class1();
A.ClassOneFunction(); // won't work because Function2 is a function of Class1
The one that doesn't work:
Class2 C = new Class2();
..is because Class2 in your code is abstract. You simply cannot instantiate instances of abstract classes. They are there to be inherited from.. not instantiated.
The inconsistent accessibility error is because internal is less accessible than public. If your method is internal.. then it isn't visible outside of the assembly.

Here is some basic difference between modifiers:
this would help you
protected:
The type or member can only be accessed by code in the same class or struct, or in a derived class.
internal:
The type or member can be accessed by any code in the same assembly, but not from another assembly.
protected internal:
The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.
protected internal; only derived types or types within the same assembly can access that member, so they need to be in the same Dynamic Link Library or an executable file.

Related

C# calling overridden method from base class

I'm overriding some existing codes but try not to touch the existing classes.
I have a base class
public class A {
public virtual void Func() {
do something...
}
}
I have several other classes is accessing it by calling A.Func()
I'm writing an extension class
public class B : A {
public override void Func() {
do something else...
}
}
Without touching the base and those classes calling the base class, is there any way to point the method Func() to the extended class?
I mean when there's a class calling A.Func(), it executes the B.Func() instead A.Func()
But without touching the code from that class nor the A class
An example
public class C {
void SomeOutsideFunc()
{
var a = new A();
a.Func(); //in here, is it possible to execute the extended B class's Func()?
}
}
in above example
class A and class C is forbidden for any modification
class B is an extended class I coded.
right now, I have to make another override to class C to make things working
my issue is there are a lot of C type classes (none of those that I can make any changes)
tks
You can create the object of base class which is pointing to the child class, suppose B.
A objA=new B();
objA.Func();
This will call the function of derived class.
What you're describing is how things already work. Imagine you have these two classes:
public class BaseClass
{
public virtual void WriteSomething()
{
Console.WriteLine("base write something");
}
}
public class DerivedClass : BaseClass
{
public override void WriteSomething()
{
Console.WriteLine("derived write something");
}
}
If you create an instance of BaseClass and call WriteSomething, you get "base write something":
BaseClass instance = new BaseClass();
instance.WriteSomething();
// "base write something" is printed to the console
Likewise, creating an instance of DerivedClass and calling WriteSomething results in "derived write something":
DerivedClass instance = new DerivedClass();
instance.WriteSomething();
// "derived write something" is printed to the console
Even if we assign that instance to a BaseClass variable, we still get "derived write something":
DerivedClass instance = new DerivedClass();
BaseClass instanceAsBaseClass = instance;
instanceAsBaseClass.WriteSomething();
// "derived write something" is printed to the console
So we can clearly then pass this into a method as BaseClass but still use the overriden methods from the derived class:
public static void DoSomeThings(BaseClass instance)
{
instance.WriteSomething();
}
BaseClass instance = new DerivedClass();
DoSomeThings(instance);
// "derived write something" is printed to the console
Note that we haven't changed the DoSomeThings method.
Try it online

What is the difference between a sealed class and a private class? [duplicate]

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();
}
}
}

Hiding/restricting generic base class direct usage from other assemblies [duplicate]

I have a common assembly/project that has an abstract base class, then several derived classes that I want to make public to other assemblies.
I don't want the abstract base class to show up in these other assemblies in Intellisense, so I thought I'd make it internal, but I get this error:
Inconsistent accessibility: base class 'Settings' is less accessible than class 'IrcSettings' ....
I don't really get this. I am forced to make the abstract Settings class public, and thus visible outside this assembly.
How can I make this class internal instead?
As I understand, you want your abstract class to only be implemented by other classes in the same assembly (e.g. it is internal) but the derived classes could be public.
The way to do this is to make the abstract base class public, but give it an internal default constructor:
public abstract class MyClass
{
internal MyClass() { }
}
This will allow MyClass (and hence its members) to be visible and usable to classes outside your assembly, but classes outside your assembly cannot inherit from it (will get a compile error).
Edit: If classes which can be seen by external assemblies inherit from MyClass, you cannot prevent MyClass from also being seen - e.g., showing up in Intellisense. However, you can prevent them from being used by following the above.
The abstract base class has to be public, as the entire inheritance heirarchy for a class has to be visible. This ensures the polymorphism works and is valid; however all the base classes' members can be internal (including the constructor), and hence not usable outside your assembly
There really isn't much of a benefit to what you're trying to achieve but what you're actually looking to achieve is similar to this.
Have your abstract base class in 1 assembly with everything internal. In the AssemblyInfo for that assembly you need to add
[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
Then in another assembly you have all the classes you want publicly available. Note you will still be able to access the base class from intellisense for any code inside cs_friend_assemblies_2 or whatever you name your assembly but not any where else.
You can't simultaneously make the class available to other assemblies for inheritance but also private so it can't be visible to other consumers. You can make the class internal, and expose it to a specific assembly (if it's a friend assembly) using the [InternalsVisibleTo] attribute, but I don't think this is what you want.
If you want to keep code (other than derived classes) from being able to instantiate your base class, you could give it a protected constructor:
abstract class MyBaseClass
{
protected MyBaseClass() { ... } // only inheritors can access this...
}
You can hide the class members from Intellisense using the EditorBrowsable attribute:
abstract class MyBaseClass
{
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void SomeMethodToBeHidden() { }
}
It should be noted that some people have reported problems with the IDE not always respecting this attribute.
As far as I'm concerned, this is a non-problem. Observe:
public abstract class Foo {
public void virtual Bar() {
// default implementation
}
}
public class NormalFoo : Foo { }
public class SpecialFoo : Foo {
public override void Bar() {
// special implementation
}
}
var foolist = new List<Foo>();
foolist.Add( new NormalFoo() );
foolist.Add( new SpecialFoo() );
foreach (var f in foolist) {
f.Bar();
}
The above wouldn't work at all without polymorphism -- being able to refer to instances of different derived classes through their common interface, the abstract base class. What you want to do is take that away and cripple the usability of your class hierarchy. I don't think you should continue down this path.
Will the other assemblies ever inherit from your abstract base class or any of the public classes that do inherit from your abstract base class?
If so, you have to make the abstract base class public. Just make methods you don't want visible outside the assembly internal.
If not, maybe interfaces can help? Define public interfaces, make your public classes implement them, and provide a factory to get instances. That way the only thing intellisense sees outside the assembly is the interface.
Does that help?
A way to work around this limitation is to use composition instead of inheritance (there are other good reasons to do this too). For example, instead of:
internal abstract class MyBase
{
public virtual void F() {}
public void G() {}
}
public class MyClass : MyBase // error; inconsistent accessibility
{
public override void F() { base.F(); /* ... */ }
}
Do this:
public interface IMyBase
{
void F();
}
internal sealed class MyBase2 : IMyBase
{
public void F() {}
public void G() {}
}
public sealed class MyClass2 : IMyBase
{
private readonly MyBase2 _decorated = new MyBase2();
public void F() { _decorated.F(); /* ... */ }
public void G() { _decorated.G(); }
}
You can omit the IMyBase interface entirely if the public doesn't need to know about it and your internals don't either.

Instantiate a class (or derived) with internal constructor

let's say I have a class defined in an assembly with:
public class BaseClass
{
internal BaseClass()
{
}
}
And in another assembly, I would like to instanciate this class with :
BaseClass c = new BaseClass();
I get the CS0143 error.
Trying another way, I try to create a derived class of the first one :
public class DerivedClass : BaseClass
{
}
but same error.
The BaseClass is not sealed. How can I instantiate this class or a derived one? Of course, I can't modify the BaseClass.
You'll have to use reflection to get the internal constructor and invoke it:
var ci = typeof(BaseClass).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
var instance = (BaseClass)ci.Invoke(new object[0]);
Since the existence of the constructor is only discovered at run-time, this approach will break if the constructor of BaseClass is changed or removed.
1) You want an actual instance of the base class:
There needs to be some method in the assembly that it's in that constructs it for you. This would normally be called a "factory". It might look like this:
public class BaseFactory
{
public static BaseClass Create() { return new BaseClass(); } //may also add other creation logic
}
Note that such a creation method may even be in BaseClass itself, or it could be in another class. (If the constructor was private it would need to be in the class itself.)
2) You want an instance of the derived class. (Perhaps you're not supposed to be able to construct the base class. If this is true it probably should be abstract.)
public class Derived : BaseClass { }
public class Foo
{
public void Bar() { Derived d = new Derived();}
}
It's hard to tell from your question if DerivedClass is in the same assembly as BaseClass. If it is, just instantiate the derived class:
BaseClass c = new DerivedClass();
And, like Branko stated, if you have control of the project in which BaseClass lives, you can use InternalsVisibleTo.

How to prevent inherited classes instances

I want to force any class not to be able to create a new instance if it inherits a specific base class, so how this base class should look like?
The following code is in java. just to give you an Example
Base class has an exception on the constructor.
public class BaseClass
{
public BaseClass()
{
throw new AssertionError();
}
}
The child class extending the base class but if you create an object of it it will give u an exception.
public class MainClass extends BaseClass
{
public MainClass()
{
}
public static void main(String[] args) {
MainClass c = new MainClass();
}
}
You want to seal your base class.
public sealed class BaseClass
{
public BaseClass(){};
}
public class SubClass : BaseClass
{
public SubClass(){};
}
This will throw a compiler error because you cannot inherit from a sealed base.
You can't specify that in the baseclass, any deriving class is self responseable, if it wants to present the ability to be derived from, than you can't do anything about it.
you can declare the base class as const - that way other classes cant extend it.
You can't do this. Please specify why you want to do this.

Categories

Resources