This code:
abstract class C
{
protected abstract void F(D d);
}
class D : C
{
protected override void F(D d) { }
void G(C c)
{
c.F(this);
}
}
Generates this error:
Cannot access protected member 'C.F(D)' via a qualifier of type 'C'; the qualifier must be of type 'D' (or derived from it)
What in the world were they thinking? (Would altering that rule break something?) And is there a way around that aside from making F public?
Edit: I now get the reason for why this is (Thanks Greg) but I'm still a bit perplexed as to the rational; given:
class E : C
{
protected override void F(D d) { }
}
Why shouldn't D be able to be able to call E.F?
The error message is edited so I might have put a typo in there.
The reason this doesn't work is because C# doesn't allow cross-hierarchy calling of protected methods. Say there was a class E that also derived from C:
C
/ \
D E
Then the reference you're trying to call the method on could actually be an instance of type E and thus the method could resolve at runtime to E.F. This is not permitted in C# as D cannot call E's protected methods, because E is in another branch of the hierarchy, i.e.
var d = new D();
var e = new E();
d.G(e); // oops, now this will call E.F which isn't allowed from D
This makes sense because the keyword protected means the member "is accessible within its class and by derived class instances" and E.F is not a member of D.
The "protected" keyword means that only a type and types that derive from that type can access the member. D has no relationship to C therefore cannot access the member.
You have a couple of options if you want to be able to access that member
Make it public
Make it internal. This will allow any types to access the member within the same assembly (or other assemblies should you add friend's)
Derive D from C
EDIT
This scenario is called out in section 3.5.3 of the C# spec.
The reason this is not allowed is because it would allow for cross hierarchy calls. Imagine that in addition to D, there was another base class of C called E. If your code could compile it would allow D to access the member E.F. This type of scenario is not allowed in C# (and I believe the CLR but I don't 100% know).
EDIT2 Why this is bad
Caveat, this is my opinion
The reason this is now allowed is it makes it very difficult to reason about the behavior of a class. The goal of access modifiers is to give the developer control over exactly who can access specific methods. Imagine the following class
sealed class MyClass : C {
override F(D d) { ... }
}
Consider what happens if F is a somewhat time critical function. With the current behavior I can reason about the correctness of my class. After all there are only two cases where MyClass.F will be called.
Where it's invoked in C
Where I explicitly invoke it in MyClass
I can examine these calls and come to a reasonable conclusion about how MyClass functions.
Now, if C# does allow cross hierarchy protected access I can make no such guarantee. Anyone in a completely different assembly can come by and derive from C. Then they can call MyClass.F at will. This makes it completely impossible to reason about the correctness of my class.
Even though D is inherits from C, D cannot access C's protected members. D can access D's protected (and private!) members, so if you put another instance of D in there instead of C everything would work. But as Greg stated, C could really be something completely different, and because the compiler doesn't know what C really is, it has to prevent D from accessing something D may not actually be able to access.
A series of posts explaining this from the C# compiler's perspective:
Why Can't I Access A Protected Member From A Derived Class
Why Can't I Access A Protected Member From A Derived Class, Part Two: Why Can I?
This limitation can be bypassed by using a static protected method:
abstract class C
{
protected abstract void F (D d);
// Allows calling F cross-hierarchy for any class derived from C
protected static void F (C c, D d)
{
c.F(d);
}
}
class D : C
{
protected override void F (D d) { }
void G (C c)
{
// c.F(this);
F(c, this);
}
}
This isn't perfect from security point of view (anyone can derive from C), but if all you care about is hiding method F from the public interface of the class C, this trick may be useful.
Simply put: accessing an instance's protected member is taken as a public access, even if you try to do so from within a derived class. Hence, it's denied.
There are many answers here and there, but none of them made it clear to me "why I can't access the protected members of a parent class from a child". That above is what I understood after looking at my code again after reading these confusing answers.
Example:
class Parent
{
protected int foo = 0;
}
// Child extends from Parent
class Child : Parent
{
public void SomeThing(Parent p)
{
// Here we're trying to access an instance's protected member.
// So doing this...
var foo = p.foo;
}
}
// (this class has nothing to do with the previous ones)
class SomeoneElse
{
public void SomeThing(Parent p)
{
// ...is the same as doing this (i.e. public access).
var foo = p.foo++;
}
}
You'd think you'd have access to p.foo because you're inside a child class, but you're accessing it from a instance, and that's like a public access, so it's denied.
You're allowed to access protected members from within the class, not from an instance (yes, we know this):
class Child : Parent
{
public void SomeThing()
{
// I'm allowed to modify parent's protected foo because I'm
// doing so from within the class.
foo++;
}
}
Finally, for the sake of completeness, you are actually able to access an instance's protected and even private members only if you're doing so within the same class:
class Parent
{
protected int foo = 0;
private int bar = 0;
public void SomeThing(Parent p)
{
// I'm allowed to access an instance's protected and private
// members because I'm within Parent accessing a Parent instance
var foo = p.foo;
p.bar = 3;
}
}
To understand why this kind of behavior makes sense let's consider why we need access modifiers at all in object oriented programming languages. We need them to limit a scope where a particular class member can be used. And that in turn simplifies searching for the usages.
To summarize:
to find all usages of public member one needs to search through entire project (and this is not enough in case of library that is used by independent developers)
to find all usages of protected member one needs to search through the container class and all its subclasses
to find all usages of private member one needs to search through the container class.
So if the compiler allowed to call protected method from superclass in the described way we could end up with cross-hierarchy calling of protected methods as described in this answer. And in such situation one had to search through all the children of the most parent class that defines the member. And that would increase the scope.
PS. The same behavior is implemented in Java.
Yes, it is possible. We will most probably have such an example very soon.
To do that you must do the following:
Inherit the default form (EditAppointmentDialog) and do your customization (you can even use the winforms designer for that).
public partial class CustomAppointmentEditDialog : EditAppointmentDialog
{
private RadComboBox cmbShowTimeAs = null;
public CustomAppointmentEditDialog()
{
InitializeComponent();
this.cmbShowTimeAs = this.Controls["cmbShowTimeAs"] as RadComboBox;
}
private void chkConfirmed_ToggleStateChanged(object sender, StateChangedEventArgs args)
{
this.cmbShowTimeAs.SelectedValue = (args.ToggleState == ToggleState.On) ?
(int)AppointmentStatus.Busy : (int)AppointmentStatus.Tentative;
}
}
In the above code I have added an additional check box and set the status (show time as) of the appointment to Tentative if it is unchecked or to Busy if it is checked. The strange way of accessing the combo box is because it is private currently. This will be changed for the upcoming Q1 2009 release.
Subscribe to AppointmentEditDialogShowing event of RadScheduler and substitute the default form with your customized one:
private IEditAppointmentDialog appointmentEditDialog = null;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.radScheduler1.AppointmentEditDialogShowing += new EventHandler<AppointmentEditDialogShowingEventArgs>(radScheduler1_AppointmentEditDialogShowing);
}
void radScheduler1_AppointmentEditDialogShowing(object sender, Telerik.WinControls.UI.AppointmentEditDialogShowingEventArgs e)
{
if (this.appointmentEditDialog == null)
{
this.appointmentEditDialog = new CustomAppointmentEditDialog();
}
e.AppointmentEditDialog = this.appointmentEditDialog;
}
I hope this helps. Do not hesitate to write me back if you have further questions.
Related
I have a class B that is a subclass of class A. I create an object of type B and call OnlyA() on it, but inside OnlyA() the call to OnlyB() causes a compiler error.
From my understanding, OnlyB() is the same as this.OnlyB() and the method called should be chosen from the object's class (B), not the current class where code is being executed (A). This is why the call to Both() calls the method in B, not A. So why is it searching for OnlyB() in A, not B? How am I supposed to know when the method called is chosen from the object's class or the current class?
class Program
{
static void Main(string[] args)
{
B bRefB = new B();
bRefB.OnlyA();
}
}
class A
{
public void OnlyA()
{
Console.WriteLine("In A - OnlyA()");
OnlyB(); // compiler error
Both(); // calls the method in B
}
public virtual void Both()
{
Console.WriteLine("In A - Both()");
}
}
class B : A
{
public void OnlyB()
{
Console.WriteLine("In B - OnlyB()");
}
public override void Both()
{
Console.WriteLine("In B - Both()");
}
}
You are absolutely correct that OnlyB is the same as this.OnlyB. And that's the issue; this is of type A. It has no knowledge that B even exists (nor should it).
Superclasses do not, and are not supposed to, have any knowledge about the fact that they have derived classes at all let alone what methods are in them. Its not an issue of "searching"; what happens when you have C that doesn't define OnlyB? What method would be called?
Subclasses on the other hand are always subclasses of the super class; and so it is safe for them to invoke base class methods.
Bradely's answer covers why your code does not work (this is of type A). Here is correct way to write your requirements as code.
You want to call method based on run-time type of an object. Since compile time of this is type of the current object you need to cast it in some way to derived type before calling. Possible options:
just cast - statically checked that B has OnlyB, cast exception at run-time:
((B)this).OnlyB();
use dynamic - no static type checking, exception at run time if actual class does not have OnlyB method irrespective if it is from B, C...
dynamic b = this;
b.OnlyB();
manual reflection call (same as dynamic).
generics - see Curiously Recurring Template Pattern and generics constraints (C#)
I'm a C++ developer learning C#, and I'm in a situation where I need a class C to have two members that belong to it that represent "robots." The robots need to be able to access private members of C, and they don't need to be used anywhere else. In C++ I'd use the "friend" keyword, but I don't know what to do here. I thought about doing something like this:
class C
{
private Member mem;
private Robot bot;
private class Robot
{
C owner;
public void function() { //Robot needs to use owner.mem here,
//but can't because it's private}
};
}
The trouble is that I don't know how to say that a Robot is "owned" by an instance of C, and can access its members.
One way to do it is to pass the outer class's instance to the inner class's constructor as a reference.
class C
{
private Member mem;
private Robot bot;
private class Robot
{
C owner;
public Robot(C c) {owner = c;}
public void function()
{
// Robot can use owner.mem here
}
};
}
There's no direct equivalent of friend - the closest that's available (and it isn't very close) is InternalsVisibleToAttribute but it breaks the relationships between classes and undermines some fundamental attributes of an OO language.
The only decent solution that has occurred to me is to invent an interface, ICClass, which only exposes the public methods, and have the Factory return ICClass interfaces.
This involves a fair amount of tedium - exposing all the naturally public properties again in the interface.
There are heaps of threads about this: Why does C# not provide the C++ style 'friend' keyword?
"Robot needs to use owner.mem here, but can't because it's private"
I think you want Protected with an inheritance model:
class C
{
protected Member mem;
protected Robot bot;
}
private class Robot : C
{
public void function() {
base.mem... // here you can use the base classes mem and bot
};
}
Within my projects I often want to have a method (or function if you prefer) that is private, however I also want to access it from ONE other class. Is this a possibility?
To clarify, this method can be accessed from ClassA, its own class but not any other.
There are plenty of ways to do this untill your last statement that is "and ONLY that class", i can only think of 1 way to do that and it is to have the classes laid out in assemblies as such as such:
Assembly A only contains class A with the method you want declared as internal
Assembly B declared as a friendly assembly : https://msdn.microsoft.com/en-us/library/0tke9fxk.aspx and contains code to call A (it can as to it it is internal as if in the same assembly as it is a friend assembly)
No other assembly linked to A , B or both will be able to call the method on class A as it is internal.
The best way that I can think of is this.
In C# 5, a set of caller information attributes were added, namely [System.Runtime.CompilerServices.CallerMemberName], [System.Runtime.CompilerServices.CallerFilePath], and [System.Runtime.CompilerServices.CallerLineNumber]. We can use the CallerFilePathAttribute to see whether the caller comes from a particular .cs file.
Usually, one file will only contain one class or struct. For example, ClassA is defined in ClassA.cs. You can check if the caller file name matches ClassA.cs in the method.
So modify your method's parameters like this:
([CallerFilePath] string callerFilePath = "" /*Other parameters*/)
In the method, check if the callerFilePath matches the file path of ClassA. If it does not, throw an exception saying that the method can only be accessed from ClassA!
You can make this method protected, if it suits your OOP structure:
public class A
{
protected void Test()
{
Console.WriteLine("I can only be called from B");
}
}
public class B : A
{
public void Pub()
{
Test();
}
}
And there many other ways to do this.
However, in general, it sounds like a wrong look at access modifiers.
If you want to only call your method from exactly one place, then just call it from exactly one place.
The fact that this method should be called from another class, makes him public, logically and architecturally.
Another simple way to control member access is using delegates.
Let's assume you have a private method:
class SecureMethod {
private void DoSomething() { }
}
You can provide access to this method by injecting delegate to this method:
class ClassA {
public ClassA(Action secureMethod) { }
}
SecureMethod objWithSecureMethod;
var a = new ClassA( objWithSecureMethod.DoSomething );
I'm showing you how do to this, but these are very bad practices:
public class A
{
private void CanOnlyCallMethodInClassB();
public static void SetHandlerCanOnlyCallMethodInClassB(ClassB b)
{
b.MethodFromClassA = CanOnlyCallMethodInClassB;
}
}
public class B
{
public Action MethodFromClassA { get; set; }
}
in code:
var b = new B();
A.SetHandlerCanOnlyCallMethodInClassB(b);
b.MethodFromClassA();
but better way is to use object of ClassB in method's classA. Search google for strategy pattern or use inheritance.
Whatever you are asking is not possible in C#. I mean you can not allow only one class to use private method. All you can do is to use internal which allows classes of just one assembly to access your methods or protected which is accessible within its class and by derived class instances!
Apart from that There is not any thumb rule for what you are asking but you can do some hack as shown below:
MethodInfo privateMethod = instance.GetType().GetMethod("NameOfPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
privateMethod.Invoke(instance, new object[] { methodParameters });
One slightly dirty trick to use a method from class B in class A is to make the method protected rather than private and derive A from B.
Another possibility, probably better, is to make the method internal rather than private and then put class A and B in the same assembly.
In C#, we can not change access modifier while overriding a method from base class.
e.g.
Class Base
{
**protected** string foo()
{
return "Base";
}
}
Class Derived : Base
{
**public** override string foo()
{
return "Derived";
}
}
This is not valid in C#, It will give compile time error.
I want to know the reason, why it's not allowed. Is there any technical problem or can it lead to something which is not consistent in terms of access restriction???
Changing the access modifier of a method in a derived type is pointless that's why it's not allowed:
Case 1: Override with a more restrictive access
This case is obviously not allowed due to the following situation:
class Base
{
public virtual void A() {}
}
class Derived: Base
{
protected override void A()
}
Now we could say:
List<Base> list;
list.Add(new Derived());
list[0].A() //Runtime access exception
Case 2: Overriding with a less restrictive access modifier
What is the point? Hide the method and you are done.
Obviously if someone calls through the base type they will not have access to the new method defined in the derived type but that is consistent with how the author of the base type wanted things to be so you have no "right" to change that. If you want the specifics of the derived class call from the derived class, in which case the new method works perfectly fine.
EDIT: Expanding case 2
What I am trying to say in case 2, is that you already have the means to change accessibility of any method (virtual or not) if you want to change accessibility.
Consider the following code:
public class Base
{
protected virtual string WhoAmI()
{
return "Base";
}
}
public class Derived : Base
{
public new virtual string WhoAmI()
{
return "Derived";
}
}
public class AnotherDerived : Derived
{
public override string WhoAmI()
{
return "AnotherDerived";
}
}
With the new keyword you have effectively created a new virtual method for your Derived class with the same name and signature. Take note that it is ALLOWED to declare a new method virtual, so any class deriving from Derived will be allowed to override it.
What is not allowed is to have someone do the following:
Base newBaseObject = new Derived();
newBaseObject.WhoAmI() //WhoAmI is not accessible.
But this fact has nothing to do with being able to override WhoAmI() or not. Whatever the case this situation can never be because Base does not declare a public WhoAmI().
So in a theoretical C# where Derived.WhoAmI() could override Base.WhoAmI() there is no practical benefits in doing so because you will never be able to call the virtual method from the base class anyways, so the new option already meets your requirements.
I hope this makes it clearer.
OK, I found a small note from Eric Lippert in the Annotated C# reference:
An overridden virtual method is still considered to be a method of the class that introduced it. The overload resolution rules in some cases prefer members of more derived types ... overriding a method does not "move" where that method belongs in this hierarchy.
So this is an intentional rule to prevent the 'brittle base class' problem and provide better versioning, ie less problems when a base class changes.
But note that it has nothing to do with security, type-safety or object-state.
If you change visibility modifiers from a more restrictive modifier to a less restrictive modifier you allow class clients access to methods designated for internal use. Essentially you've provided a means to alter class state that may not be safe.
Reducing visibility is impossible because if Base.Member was visible and Derived.Member was not visible, that would break the whole “Derived is a Base” concept in OOP. However, increasing visibility is disallowed maybe because the language developers think that changing the visibility would be a mistake most of the time. However, you can always use the new keyword to hide base class members by introducing a member with the same name but a different behavior. This new member belongs to the derived type’s interface, so of course you can still access the base type’s interface by casting to that base type. Depending on how you write your subclass, your new member might effectively increase the visibility of the base class’s property—but remember that the base class’s property can still be accessed directly (e.g., a subclass of your subclass could cast this to Base and bypass your property).
The question here is how to both override and new the same named member (identifier) in a subclass. That is apparently not possible. At the very least, I can say through experimentation that public new override string foo(){return "";} is not a syntax for that. However, you can get the same effect by using two subclasses:
using System;
class Base
{
protected virtual string foo()
{
return "Base";
}
public void ExhibitSubclassDependentBehavior()
{
Console.WriteLine("Hi, I am {0} and {1}.", GetType(), foo());
}
}
abstract class AbstractDerived : Base
{
protected virtual string AbstractFoo()
{
return base.foo();
}
protected override string foo()
{
return AbstractFoo();
}
}
class Derived : AbstractDerived
{
protected override string AbstractFoo()
{
return "Deprived";
}
public new string foo()
{
return AbstractFoo();
}
}
static class Program
{
public static void Main(string[] args)
{
var b = new Base();
var d = new Derived();
Base derivedAsBase = d;
Console.Write(nameof(b) + " -> "); b.ExhibitSubclassDependentBehavior(); // "b -> Hi, I am Base and Base."
Console.WriteLine(nameof(d) + " -> " + d.foo()); // "d -> Deprived"
Console.Write(nameof(derivedAsBase) + " -> "); derivedAsBase.ExhibitSubclassDependentBehavior(); // "derivedAsBase -> Hi, I am Derived and Deprived."
}
}
The intermediate subclass (AbstractDerived) uses override and introduces a new, differently-named member that the subclass and sub-subclasses can continue to override the base class’s member as they see fit. The sub-subclass (Derived) uses new to introduce the new API. Since you can only use new or override with a particular identifier only once per level of subclassing, you need two levels of subclassing to effectively use both on the same identifier.
So, in a way, you can change the visibility while overriding methods—it’s just a pain and there’s no syntax I know of to accomplish it with just one level of inheritance. However, you might have to use some trick like this depending on what interfaces you’re trying to implement and what your base class looks like. I.e., this may or may not be what you actually want to do. But I still wonder why C# does not just support this to begin with. IOW, this “answer” is just a re-expression of the OP’s question with a workaround ;-).
You can make derived class's access less than the base's, but not more. Otherwise it would contradict base's definition and expose its components beyond what was intended.
Reasons are obvious. Security and Integrity of the objects.
In this particular example, what if external entities start modifying the property of the object which is protected according the base-class. Things will go haywire. What about the client-code that is written against the base-class to which all/any derived class must conform to.
if it had different access modifiers you can't really consider it the same method any more. kind of suggests a problem with the design of the model.
a better question would be why would you want to change the access modifiers?
Overriding is a term which enables you to change or augment the behavior of methods in a base class. Overriding gives you the control to write new logic for an existing method.
Changing the method signature of a base class is somewhat like writing a new method instead of overriding the existing one. It contradicts the purpose of overriding a method. So maybe the reason why you cannot change the access modifier while overriding methods in C#.
I have created a class say A which has some functions defined as protected.
Now Class B inherits A and class C inherits B. Class A has private default constructor and protected parameterized constructor.
I want Class B to be able to access all the protected functions defined in Class A but class C can have access on some of the functions only not all the functions and class C is inheriting class B.
How can I restrict access to some of the functions of Class A from Class C ?
EDIT:
namespace Db
{
public class A
{
private A(){}
protected A(string con){assign this value}
protected DataTable getTable(){return Table;}
protected Sqlparameters setParameters(){return parameter;}
}
}
namespace Data
{
public class B:A
{
protected B():base("constring"){}
protected DataTable output(){return getTable();}
protected sqlparameter values(param IDataParameter[] parameter){}
}
}
namespace Bsns
{
public class C:B
{
protected C():base(){}
protected DataTable show()
{return values(setparameter());}
}
}
EDIT
I think what I am trying to do here is Multiple inheritance.
Please check.
class A
{
//suppose 10 functions are declared
}
class B:A
{
//5 functions declared which are using A's function in internal body
}
class C:B
{
//using all functions of B but require only 4 functions of A to be accessible by C.
}
You need to have classes A and B in the same assembly and class C in another assembly. You can mark the member you want to restrict access to by derived classes as protected internal. This makes the member, well, protected and internal. As far as limiting class C's access to the member it will suffice to mark it internal. Since this will make it it public within the first assembly, you might want to add protected to enforce encapsulation.
Turns out marking a member protected internal doesn't make it private to classes outside of the assembly. Seems that for all intents and purposes protected internal is the same as protected. Unfortunately the only way I can see achieving this would be to mark it internal and put up with the member being public to the defining assembly.
Even C# programming guide on MSDN gets it wrong:
By combining the protected and
internal keywords, a class member can
be marked protected internal — only
derived types or types within the same
assembly can access that member.
Phil Haack explains:
protected internal means protected OR
internal
It’s very clear when you think of the
keywords as the union of accessibility
rather than the intersection. Thus
protected interna means the method is
accessible by anything that can access
the protected method UNION with
anything that can access the internal
method.
Here is the updated code:
class A {
protected void Test3(){} //available to subclasses of A in any assembly
protected internal void Test() { } //Same as protected :(
public void Test2(){}//available to everyone
internal void Test4(){} //available to any class in A's assembly
}
class B : A {
void TestA() {
Test(); //OK
}
}
//Different assembly
class C : B {
void TestA() {
Test4(); //error CS0103: The name 'Test4' does not exist in the current context
}
}
It looks like you should probably using Composition not Inheritance.
Class A implements calc() and allow().
Class B has a private A but isn't derived from A
Class C derives from B and has no access to the private A object in class B.
I'd suggest that you rethink your design. Maybe there is a simpler way. What if C uses an instance of B instead of deriving from it (composition) ? That way C can use B's public methods but not get access to the protected ones.
Class A should not care about the level/depth of a descendant. If something is marked protected, it should be protected for both B and C (regardless of the depth of the inheritance chain).
B may choose to delimit its descendants by tightening the constraints (but this is rare).
If you can tell me more about your context - the problem you are trying to solve.. I can give you a more detailed/useful answer.
As others have said, you probably want to use composition instead of inheritance.
class A {
protected void Foo() { … }
protected int Bar() { … }
}
class B {
private A a;
public B() {
this.a = new A();
}
protected int Bar() {
return a.Bar();
}
}
class C : B { … }
Looking at your example, though, I would question whether C should inherit from B, or whether it should really just hold a reference to an object of type B.
Personally, I wouldn't go putting classes in different assemblies just for the purpose of restricting access if the class doesn't otherwise logically belong in a different assembly. There are other ways to handle it.