Accessing protected members in a different assembly - c#

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.

Related

Why am I getting: The type 'IThirdParty' is defined in an assembly that is not referenced. You must add a reference to assembly 'ThirdPartyAssembly'?

Suppose there is third party assembly ThirdPartyAssembly.dll that expose following:
namespace ThirdPartyAssembly
{
public interface IThirdParty
{
void GetInstance(ThirdPartyInfo info);
}
public class ThirdPartyInfo
{
public ThirdPartyInfo(string instanceText);
public string InstanceText { get; set; }
}
}
At one of the solution's project MyAssembly I refer ThirdPartyAssembly.dll and implement following code:
namespace MyAssembly
{
public abstract class AbstractMyClass1 : IThirdParty
{
void IThirdParty.GetInstance(ThirdPartyInfo info)
{
info.InstanceText = "some-text";
}
}
public abstract class AbstractMyClass1Consumer<T>
where T : AbstractMyClass1
{
}
}
At second solution project MyAssemblyConsumer I refer MyAssembly (as solution project reference) and implement following classed
namespace MyAssemblyConsumer
{
class MyClass1 : AbstractMyClass1
{
}
class MyClass1Consumer : AbstractMyClass1Consumer<MyClass1>
{
}
}
Everything compiles fine so far.
However, when I add IMyClass2 into MyAssembly project that inherits IThirdParty interface with following abstract classes
namespace MyAssembly
{
public interface IMyClass2 : IThirdParty
{
}
public abstract class AbstractMyClass2 : IMyClass2
{
void IThirdParty.GetInstance(ThirdPartyInfo info)
{
info.InstanceText = "some-text";
}
}
public abstract class AbstractMyClass2Consumer<T>
where T : IMyClass2
{
}
}
And try to implement following classes into MyAssemblyConsumer
namespace MyAssemblyConsumer
{
class MyClass2 : AbstractMyClass2
{
}
class MyClass2Consumer : AbstractMyClass2Consumer<MyClass2>
{
}
}
I'm getting following compilation error on MyClass2Consumer:
The type 'IThirdParty' is defined in an assembly that is not referenced. You must add a reference to assembly 'ThirdPartyAssembly'
The question why I don't need to refer ThirdParty.dll at first case, but need this reference in the second case?
This is happening because in first case you "hide" your reference to ThirdPartyAssembly.dll. Yes, your public AbstractMyClass1 implements IThirdParty from it, but it implements it implicitly so the only way to call IThirdParty.GetInstance() method is like this:
var myClass1Instance = new MyClass1();
var info = new ThirdPartyInfo();
(myClass1Instance as IThirdParty).GetInstance(info); // this can be called
myClass1Instance.GetInstance(info); // <- this method doesn't exists
So at compile time of your MyAssemblyConsumer project compiler doesn't need to know anything about IThirdParty. As you said your first case is compiling successfully, I suppose you don't have any code like this.
In your second case you expose IThirdParty of ThirdPartyAssembly.dll by your public IMyClass2 interface. In this case compiler must know about IThirdParty interface at compile time (on that line where you defining AbstractMyClass2Consumer<T>), that's why you get this exception.

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

Defined Elements cannot be explicitly declared as private or protected

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
{
}
}

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

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.

Inheritance in C# from abstract classes

I have a question regarding inheritance in C#. I have a public abstract class A that defines protected virtual members. I have another abstract class B that inherits from A, and then another internal class C, inheriting from B. The first class A is in a separate namespace, and the other two are in the same namespace, but include a reference to the first.
I was trying to access the protected virtual member of A in C using base keyword, but am unable to unless I provide a method in B and then call A's protected virtual member there.
I want to know if what I was trying to do is possible, i.e. was I doing something incorrectly? Or if its not possible, then why?
Thanks.
Here's the code sample :
namespace A
{
public abstract class BaseClass
{
protected virtual string GetData()
{
//code to get data
}
}
}
namespace B //includes a reference to A
{
abstract class DerivedClassA : BaseClass
{
}
internal class DerivedClassB: DerivedClassA
{
public void write()
{
base.GetData(); // results in error.
// The name 'GetData' does not exist in the current context
// and DerivedClassA does not contain a definition for 'GetData'
}
}
Other than a namespace issue your code ran fine, the one thing I had to change was change DerivedClassA to
abstract class DerivedClassA : A.BaseClass
{
}
What I suspect is whatever BaseClass is called in your real project you have a class of the same name in namespace B or some other namespace you have included in your using statements at the top of your code. For example this would recreate your error
namespace A
{
public abstract class BaseClass
{
protected virtual string GetData()
{
throw new NotImplementedException();
}
}
}
namespace B //includes a reference to A
{
public abstract class BaseClass
{
}
abstract class DerivedClassA : BaseClass
{
}
internal class DerivedClassB: DerivedClassA
{
public void write()
{
base.GetData(); // results in error.
// The name 'GetData' does not exist in the current context
// and DerivedClassA does not contain a definition for 'GetData'
}
}
}
Check that you don't have another namespace that uses the same name as BaseClass or explicitly define the namespace of BaseClass in DerivedClassA
This works for me.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Protectedmemberinabstractclassex
{
class Program
{
static void Main(string[] args)
{
}
}
}
namespace A
{
public abstract class BaseClass
{
protected virtual string GetData()
{
throw new NotImplementedException();
}
}
}
namespace B //includes a reference to A
{
abstract class DerivedClassA : A.BaseClass
{
}
internal class DerivedClassB : DerivedClassA
{
public void write()
{
base.GetData();
}
}
}
Got the source of the problem. Apparently, the location of the dlls that the second namespace was referring to had changed and hence, it was pointing to an outdated reference. After I updated the references from the correct location, it ran fine. Thanks all for the help.

Categories

Resources