Let's say I have,
public class A
{
public static void MyAMethod()
{
}
public class B
{
}
}
public class C : A.B
{
public void MyCMethod()
{
MyAMethod();// I need to call this
}
}
Now I need to call MyAMethod from class C.
Edit: In my situation class A is unavailable. So, I cannot use A.MyAMethod.
You can just call A.MyAMethod() from inside your method since it is static
If you take a look at the IL code for
namespace NestedTest
{
public class A
{
public static void MyAMethod()
{
System.Console.WriteLine("public static void MyAMethod()");
}
public class B
{
public void MyBMethod()
{
MyAMethod();
}
}
}
}
you will find that MyBMethod is implemented(?) as
.method public hidebysig instance void MyBMethod() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: nop
IL_0001: call void NestedTest.A::MyAMethod()
IL_0006: nop
IL_0007: ret
} // end of method B::MyBMethod
As you can see the call to NestedTest.A::MyAMethod() is hard-coded i.e. the "magic" was already done by the C#->IL compiler. (*)
You could get the information you need to call the static method via reflection, e.g. (without error handling and rather crude)
public class C : A.B
{
public void MyCMethod()
{
Type parent = GetType().BaseType;
Type outer = parent.DeclaringType;
System.Reflection.MethodInfo mi = outer.GetMethod("MyAMethod");
mi.Invoke(null, null);
return;
}
}
but there is probably a better solution for your specific problem.
(*) and the c# compiler does that only as specified in http://msdn.microsoft.com/en-us/library/ms228593.aspx
3.7 Scopes
The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name [...]
- The scope of a member declared by a class-member-declaration (§10.1.6) is the class-body in which the declaration occurs. In addition, the scope of a class member extends to the class-body of those derived classes that are included in the accessibility domain (§3.5.2) of the member.class B is part of the class-body of class A, class C is not. And class C is also not derived from class A.
Simply do
public class C : A.B
{
public void MyCMethod()
{
A.MyAMethod();// I need to call this
}
}
As the method is static you can call it from anywhere through class A
You set MyAMethod to be static, so just call A.MyAMethod() inside your MyCMehtod()
Regards
A static method, field, property, or event is callable on a class even when no instance of the class has been created. And according to the data given in Staic Members Functions. You can call a static members directly with the Class name. So, in your case
A.MyAMethod(); will do the stuff.
You can't call MyAMethod() that way directly cause it doesn't belong to class B and you are inheriting class B; instead it's a static member of class A and Hence you have to qualify it before calling A.MyAMethod();
If you would have inherited class A instead then your code would do fine cause class C will inherit the method as well.
OR
Change your code to accomodate what you want like
public class A
{
public static void method()
{
Console.WriteLine("method in base class");
}
public class B
{
public void bmethod()
{
A.method();
}
}
}
public class C : A.B
{
public void cmethod()
{
bmethod();
}
}
Related
Say I have a generic class Foo, that has a variable that is protected
public class Foo<T>
{
protected bool knowsFu;
}
I also have 2 sub-classes: Bar and Pipe
public class Bar : Foo<Bar> {}
public class Pipe : Foo<Pipe> {}
It is actually possible for me to access the knowsFu in Pipe FROM Bar, e.g.:
public class Bar : Foo<Bar>
{
void UpdateFuInOtherClass(Pipe p)
{
p.knowsFu = false;
}
}
Is this intended behaviour? (If so, what would be the usecase?)
Is there a way for me to prevent other Foo-Subclasses from modifying/reaching the protected variable inside of my current subclass?
More specifically: I'm using a generic class to implement the Singleton-Pattern:
https://en.wikipedia.org/wiki/Singleton_pattern
However, I'm currently able to access any singleton's protected instance-variable, as long as I am inside of another Singleton. Is there a way to prevent this?
EDIT: It might be relevant to note that the protected variable (knowsFu) is actually STATIC as well.
EDIT2: Ok, maybe the example was abit too generic.. here's how I'm actually currently implementing it:
why use Singleton? A:The platform I'm working on is Unity3D, in which the pattern is used frequently
I have a generically typed abstract class SingletonBehaviour
public abstract class SingletonBehaviour<T> where T : MonoBehaviour
{
public static T Instance { get { return instance; } }
protected static T instance { get; private set; } }
// Loading is done through Unitys Awake-Method
}
One of the Singleton-Objects that I'm using is the APIManager
public class APIManager : SingletonBehaviour<APIManager>
{
// Methods like SendHTTPPost(), HTTPGet(), etc.
}
However, since most of my projects need some better API-implementation than that, what I'm currently doing is:
public class ProjectAAPIManager : APIManager
{
// Overriding Instance so my return value is not APIManager but instead ProjectAAPIManager
public static new ProjectAAPIMamager Instance { get { return (ProjectAAPIManager)instance; } }
}
This ^ is the reason my (inner) instance-variable is protected, and not private.
However, because of this, any other SingletonBehaviour in my project can now access the (inner) instance-variable on my ProjectAAPIManager
public class GameController : SingletonBehaviour<GameController>
{
private void AMethod()
{
// Accessing inner variable instead of public one
ProjectAAPIManager.instance.DoSomething();
}
}
As it's only the getter, this currently does not really matter. But what if I'd need access to the setter in my subclass as well?
Also: would it be worth it to generically type my APIManager as well?
Your question is nothing short of bewildering. How can you make a protected member not be accesible from a derived class? Well, a good start is not making it protected.
protected is by definition exactly what you don't want, so don't use it! Use private instead.
If what you are asking is how to make it a readonly member when accessed from derived types, you have two options:
Declare it as readonly in the base class if possible.
Use a protected property instead with a private setter.
Many novice coders seems to think protected members aren't part of the public surface of the type but they really are, as long as the class can be extended. As such, the rules of public members apply: never expose public fields unless they are readonly or constants, use properties instead.
You should not have classes that implement your generic singleton class.
Otherwise, by default, your protected fields will be accessible by the subclasses (it's what "protected" keyword does)
Instead, you should do something like this:
class Program
{
static void Main(string[] args)
{
var barInstance = Foo<Bar>.GetInstance();
}
}
public class Foo<T> where T : new()
{
protected bool knowsFu;
private static T _instance;
public static T GetInstance()
{
if (_instance == null)
_instance = new T();
return _instance;
}
}
public class Bar
{
public Bar()
{
}
}
Edit 1:
To use a singleton, you should not make another class implement the singleton behavior (This is not how the singleton pattern works).
To use the same classes as your second example, you should do something like this.
public class SingletonBehaviour<T> where T : new()
{
public static T Instance
{
get
{
if(instance == null)
instance = new T()
return instance;
}
}
private static T instance { get; set; }
}
public class APIManager // This class should not inherit from the SingletonBehavior class
{
// Methods like SendHTTPPost(), HTTPGet(), etc.
}
public class ProjectAAPIManager : APIManager
{
public ProjectAAPIManager GetInstance() => SingletonBehavior<ProjectAAPIManager>.Instance();
}
We have the following code:
public class A
{
protected virtual void Method()
{
Console.Write("A");
}
}
public class B : A
{
protected override void Method()
{
Console.Write("B");
}
}
public class C : B
{
public void Some()
{
//How to call Method() from class A?
}
}
How to call Method() from class A in Some() method from class C?
We will assume that A and B are classes from the library and we can not change them.
Solution: https://stackoverflow.com/a/438952/8081796
B overrides Method() and A its marked as virtual and protected, the only way to call it (in its current format) is if B calls it somehow
public class B : A
{
protected override void Method()
{
base.Method();
Console.Write("B");
}
}
Or derived from A directly
public class C : A
{
public void Some()
{
Method();
}
}
virtual (C# Reference) | Microsoft Docs
The virtual keyword is used to modify a method, property, indexer, or
event declaration and allow for it to be overridden in a derived
class. For example, this method can be overridden by any class that
inherits it:
Furthermore
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
protected (C# Reference)
A protected member is accessible within its class and by derived class
instances.
If you really want Method of A to be called here (without changing implementation of A or B's Method), you have to make below changes.
Change access specifier of Method of B class to new from override.
override will override the base class method. Making it new won't do it.
Change access specifier of A and B class Methods to public instead of protected
protected members of A won't be accessible inside your C class.
With this changes, check out below code. You will see that Method from class A is getting called.
static void Main()
{
var c = new C();
c.Some();
Console.ReadKey();
}
public class A
{
public virtual void Method()
{
Console.Write("A");
}
}
public class B : A
{
public new void Method()
{
Console.Write("B");
}
}
public class C : B
{
public void Some()
{
//How to call Method() from class A?
((A)this).Method();
}
}
If you cannot make the changes described as above, then I'm afraid you can't call A's Method :O .
This is impossible, because
The implementation of a virtual member can be changed by an overriding
member in a derived class.
B change implementation of A, therefore C have only B implementation as base and have not implementation of A.
Solution: https://stackoverflow.com/a/438952/8081796
A is base class
B is derived from A and also C is derived from A
I want only B can access the method of A , C an not access of that same method of A.
class A {
protected void Foo() {
}
}
class B : A {
void Bar() {
this.Foo(); // OK
}
}
class C : A {
void Baz() {
this.Foo(); // I don't want to permit this
}
}
HOW IT POSSIBLE IN c#
I think this look like a problem for Interface segregation principle:
Clients should not be forced to depend upon interfaces that they don't
use.
But in your case this can be rephrased for the class inheritance.
Create pure base class (without a method you want to hide from class C)
public class Base
{
protected void SomeDummyMethod()
{
}
}
Then create your A class which inherit from Base and add a method you what to share for class B
public class A : Base
{
protected void YourFooMethod()
{
}
}
Create B class which inherit from A and will have access to all functionality including YourFooMethod
public class B : A
{
public void Bar()
{
this.YourFooMethod();
}
}
And finally your C class which have all base functionality except YourFooMethod method
public class C : Base
{
public void Bar()
{
this.YourFooMethod(); //Compile error: YourFooMethod is not a member of...
}
}
I suppose you could write code in class A that checks the calling class name against a white list or a black list and throws an exception in the cases you want to disallow, but I would not recommend doing this. That would be very difficult to maintain, and class A should not need to know about every class that extends it.
What you are trying to do is really honestly a bad idea.
C# (and .NET in general) has the access modifiers:
public - Anyone can access
private - Only the containing scope/type can access
protected - Only the containing type and its derived types can access
internal - Only types defined in the same Assembly (or InternalsVisibleTo Assemblies) can access
protected internal - The set-union of protected and internal can access.
You're asking for something in-between private and protected, where you can manually restrict access to named types.
This is not currently possible to enforce, at least at compile-time, in .NET - though if types A and B exist in the same assembly and C exists in a different assembly then internal would work.
At runtime you could enforce this with code-access-security, or more simply: using reflection to get the calling-class's name (this.GetType()), or use a password:
or more simpler: a password requirement:
class A {
private Boolean isAllowedAccess;
protected A(String password) {
this.isAllowedAccess = password == "12345abc";
}
protected void Foo() {
if( !this.isAllowedAccess ) throw new InvalidOperationException();
}
}
class B : A {
public B() : base("12345abc") {
}
void Bar() {
this.Foo(); // OK
}
}
class C : A {
public C() : base(null) {
}
void Baz() {
this.Foo(); // I don't want to permit this
}
}
Consider these variants:
class A
{
public virtual void Doit()
{
}
}
class B : A
{
public new virtual void Doit()
{
}
}
or
class B : A
{
public override virtual void Doit()
{
}
}
I cannot find the difference in the returned results of the call typeof(B).GetMethod("Doit");
In both cases MethodInfo.DecalringType is class B and other properties seem the same.
Do I miss something or there is no way to distinguish them?
Update:
When I ran the sample in LINQPAd I noticed slight difference in Attributes property:
for new virtual value was - PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask
for override - PrivateScope, Public, Virtual, HideBySig
Update 2:
I googled about VtableLayoutMask and came back to StackOverflow
Udate 3:
resulting code:
public static class MethodInfoExtensions
{
public static bool IsOverriden(this MethodInfo method)
{
Contract.Requires<ArgumentNullException>(method != null, "method");
return method.IsVirtual
&& !method.IsStatic
// overriden exactly in this class
&& method.ReflectedType == method.DeclaringType
// not new and not declared for the first time in the class
&& method.GetBaseDefinition() != method;
}
}
Update: The documentation seems to imply that IsHideBySig is the answer, but it does not appear to be the case in practice.
Another strategy is to rely on the presence of the NewSlot attribute:
public static bool HasNewModifier(this MethodInfo method)
{
return (method.Attributes & MethodAttributes.VtableLayoutMask)
== MethodAttributes.NewSlot;
}
Original, incorrect answer follows.
You can rely on the IsHideBySig property. It will be true if the method has the new modifier.
Note the above only applies to C# methods. The documentation elaborates with:
When a member in a derived class is declared with the C# new modifier
or the Visual Basic Shadows modifier, it can hide a member of the same
name in the base class. C# hides base class members by signature. That
is, if the base class member has multiple overloads, the only one that
is hidden is the one that has the identical signature. By contrast,
Visual Basic hides all the base class overloads. Thus, IsHideBySig
returns false on a member declared with the Visual Basic Shadows
modifier, and true on a member declared with the C# new modifier.
The DeclaringType will be different if it was hidden with new. For example, run:
public class A
{
public virtual void WillBeInheritted()
{
}
public virtual void WillBeOverridden()
{
}
public virtual void WillBeHidden()
{
}
}
public class B : A
{
public override void WillBeOverridden()
{
}
public virtual new void WillBeHidden()
{
}
}
class Program
{
public static void Main(string[] args)
{
foreach(var meth in typeof(B).GetMethods())
{
Console.Write(meth.Name);
Console.Write(": ");
Console.Write(meth.GetBaseDefinition().DeclaringType.Name);
Console.Write(" ");
Console.WriteLine(meth.DeclaringType.Name);
}
Console.Read();
}
}
The output will be:
WillBeOverridden: A B
WillBeHidden: B B
WillBeInheritted: A A
WillBeHidden: A A
ToString: Object Object
Equals: Object Object
GetHashCode: Object Object
GetType: Object Object
WillBeInheritted has A as the declaring type for both the method and the base definition's declaring type.
WillBeOverridden has A for the base definition's declaring type, B for the declaring type.
WillBeHidden has two versions, the hidden one in A and the hiding one in B. This makes sense when we consider:
B b = new B();
A a = b;
b.WillBeHidden(); // calls hiding method.
a.WillBeHidden(); // calls hidden method on same object.
You can use GetBaseDefinition to find out where this method was first declared.
For example if you let var mi = typeof(B).GetMethod("Doit"); you can check if mi.GetBaseDefinition() == mi or if mi.GetBaseDefinition().DeclaringType == typeof(B) etc.
Here is an example:
class Animal : object
{
public virtual void M()
{
}
}
class Mammal : Animal
{
public override void M()
{
}
}
class Giraffe : Mammal
{
}
static class Test
{
internal static void Run()
{
var mi = typeof(Giraffe).GetMethod("M");
Console.WriteLine(mi.ReflectedType); // Giraffe
Console.WriteLine(mi.DeclaringType); // Mammal
Console.WriteLine(mi.GetBaseDefinition().DeclaringType); // Animal
}
}
The MethodInfo instance mi represents the override as inherited (unchanged) to Giraffe. And mi.GetBaseDefinition() fetches another MethodInfo which represents instead the method Animal.M which does not carry the override keyword in the C# source.
Since we know that constructor is not inherited in the child class as i asked in the my previous question Click here to view question
I had write the code
namespace TestConscoleApplication
{
abstract public class A
{
public int c;
public int d;
private A(int a, int b)
{
c = a;
d = b;
}
public virtual void Display1()
{
Console.WriteLine("{0}{1}", c, d);
}
}
internal class B : A
{
protected string Msg;
public B(string Err)
{
Msg = Err;
}
public void Display()
{
Console.WriteLine(Msg);
}
}
class Program
{
static void Main(string[] args)
{
B ObjB = new B("Hello");
Console.ReadLine();
}
}
}
when i compile the code its showing an error
Error TestConscoleApplication.A.A(int, int) is inaccessible due to its protection level.
Then why it is showing an error.
By making the only constructor of A private, you've prevented derived classes from being able to be constructed outside A.
Derived class constructor always call the base constructor (one of). Making it private you prohibit access to it from outside. In other words you make it impossible to make an instance of A outside A.
Since you made a constructor, the compiler won't generate a default public one for this class for you.
If you want to provide access to it from the class descendant but not from outside, you should make it protected.
You need to have a constructor for A accessible to B, and use it. Also, the default base constructor is base() (i.e. the parameterless constructor), which doesn't exist on A. Here's one way you can resolve this (nonessential bits removed):
abstract public class A
{
protected A(int a, int b)
{
}
}
internal class B : A
{
public B(int a, int b, string Err)
: base(a, b)
{
}
}
constructors shouldn't be private otherwise you will not be able to create an instance of that class and won't be able to inherit it too, but if you want to create a private constructor create a public one with it too.
For more info Go here