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.
Related
I'm getting a warning from ReSharper about a call to a virtual member from my objects constructor.
Why would this be something not to do?
When an object written in C# is constructed, what happens is that the initializers run in order from the most derived class to the base class, and then constructors run in order from the base class to the most derived class (see Eric Lippert's blog for details as to why this is).
Also in .NET objects do not change type as they are constructed, but start out as the most derived type, with the method table being for the most derived type. This means that virtual method calls always run on the most derived type.
When you combine these two facts you are left with the problem that if you make a virtual method call in a constructor, and it is not the most derived type in its inheritance hierarchy, that it will be called on a class whose constructor has not been run, and therefore may not be in a suitable state to have that method called.
This problem is, of course, mitigated if you mark your class as sealed to ensure that it is the most derived type in the inheritance hierarchy - in which case it is perfectly safe to call the virtual method.
In order to answer your question, consider this question: what will the below code print out when the Child object is instantiated?
class Parent
{
public Parent()
{
DoSomething();
}
protected virtual void DoSomething()
{
}
}
class Child : Parent
{
private string foo;
public Child()
{
foo = "HELLO";
}
protected override void DoSomething()
{
Console.WriteLine(foo.ToLower()); //NullReferenceException!?!
}
}
The answer is that in fact a NullReferenceException will be thrown, because foo is null. An object's base constructor is called before its own constructor. By having a virtual call in an object's constructor you are introducing the possibility that inheriting objects will execute code before they have been fully initialized.
The rules of C# are very different from that of Java and C++.
When you are in the constructor for some object in C#, that object exists in a fully initialized (just not "constructed") form, as its fully derived type.
namespace Demo
{
class A
{
public A()
{
System.Console.WriteLine("This is a {0},", this.GetType());
}
}
class B : A
{
}
// . . .
B b = new B(); // Output: "This is a Demo.B"
}
This means that if you call a virtual function from the constructor of A, it will resolve to any override in B, if one is provided.
Even if you intentionally set up A and B like this, fully understanding the behavior of the system, you could be in for a shock later. Say you called virtual functions in B's constructor, "knowing" they would be handled by B or A as appropriate. Then time passes, and someone else decides they need to define C, and override some of the virtual functions there. All of a sudden B's constructor ends up calling code in C, which could lead to quite surprising behavior.
It is probably a good idea to avoid virtual functions in constructors anyway, since the rules are so different between C#, C++, and Java. Your programmers may not know what to expect!
Reasons of the warning are already described, but how would you fix the warning? You have to seal either class or virtual member.
class B
{
protected virtual void Foo() { }
}
class A : B
{
public A()
{
Foo(); // warning here
}
}
You can seal class A:
sealed class A : B
{
public A()
{
Foo(); // no warning
}
}
Or you can seal method Foo:
class A : B
{
public A()
{
Foo(); // no warning
}
protected sealed override void Foo()
{
base.Foo();
}
}
In C#, a base class' constructor runs before the derived class' constructor, so any instance fields that a derived class might use in the possibly-overridden virtual member are not initialized yet.
Do note that this is just a warning to make you pay attention and make sure it's all-right. There are actual use-cases for this scenario, you just have to document the behavior of the virtual member that it can not use any instance fields declared in a derived class below where the constructor calling it is.
There are well-written answers above for why you wouldn't want to do that. Here's a counter-example where perhaps you would want to do that (translated into C# from Practical Object-Oriented Design in Ruby by Sandi Metz, p. 126).
Note that GetDependency() isn't touching any instance variables. It would be static if static methods could be virtual.
(To be fair, there are probably smarter ways of doing this via dependency injection containers or object initializers...)
public class MyClass
{
private IDependency _myDependency;
public MyClass(IDependency someValue = null)
{
_myDependency = someValue ?? GetDependency();
}
// If this were static, it could not be overridden
// as static methods cannot be virtual in C#.
protected virtual IDependency GetDependency()
{
return new SomeDependency();
}
}
public class MySubClass : MyClass
{
protected override IDependency GetDependency()
{
return new SomeOtherDependency();
}
}
public interface IDependency { }
public class SomeDependency : IDependency { }
public class SomeOtherDependency : IDependency { }
Yes, it's generally bad to call virtual method in the constructor.
At this point, the objet may not be fully constructed yet, and the invariants expected by methods may not hold yet.
Because until the constructor has completed executing, the object is not fully instantiated. Any members referenced by the virtual function may not be initialised. In C++, when you are in a constructor, this only refers to the static type of the constructor you are in, and not the actual dynamic type of the object that is being created. This means that the virtual function call might not even go where you expect it to.
Your constructor may (later, in an extension of your software) be called from the constructor of a subclass that overrides the virtual method. Now not the subclass's implementation of the function, but the implementation of the base class will be called. So it doesn't really make sense to call a virtual function here.
However, if your design satisfies the Liskov Substitution principle, no harm will be done. Probably that's why it's tolerated - a warning, not an error.
One important aspect of this question which other answers have not yet addressed is that it is safe for a base-class to call virtual members from within its constructor if that is what the derived classes are expecting it to do. In such cases, the designer of the derived class is responsible for ensuring that any methods which are run before construction is complete will behave as sensibly as they can under the circumstances. For example, in C++/CLI, constructors are wrapped in code which will call Dispose on the partially-constructed object if construction fails. Calling Dispose in such cases is often necessary to prevent resource leaks, but Dispose methods must be prepared for the possibility that the object upon which they are run may not have been fully constructed.
One important missing bit is, what is the correct way to resolve this issue?
As Greg explained, the root problem here is that a base class constructor would invoke the virtual member before the derived class has been constructed.
The following code, taken from MSDN's constructor design guidelines, demonstrates this issue.
public class BadBaseClass
{
protected string state;
public BadBaseClass()
{
this.state = "BadBaseClass";
this.DisplayState();
}
public virtual void DisplayState()
{
}
}
public class DerivedFromBad : BadBaseClass
{
public DerivedFromBad()
{
this.state = "DerivedFromBad";
}
public override void DisplayState()
{
Console.WriteLine(this.state);
}
}
When a new instance of DerivedFromBad is created, the base class constructor calls to DisplayState and shows BadBaseClass because the field has not yet been update by the derived constructor.
public class Tester
{
public static void Main()
{
var bad = new DerivedFromBad();
}
}
An improved implementation removes the virtual method from the base class constructor, and uses an Initialize method. Creating a new instance of DerivedFromBetter displays the expected "DerivedFromBetter"
public class BetterBaseClass
{
protected string state;
public BetterBaseClass()
{
this.state = "BetterBaseClass";
this.Initialize();
}
public void Initialize()
{
this.DisplayState();
}
public virtual void DisplayState()
{
}
}
public class DerivedFromBetter : BetterBaseClass
{
public DerivedFromBetter()
{
this.state = "DerivedFromBetter";
}
public override void DisplayState()
{
Console.WriteLine(this.state);
}
}
The warning is a reminder that virtual members are likely to be overridden on derived class. In that case whatever the parent class did to a virtual member will be undone or changed by overriding child class. Look at the small example blow for clarity
The parent class below attempts to set value to a virtual member on its constructor. And this will trigger Re-sharper warning, let see on code:
public class Parent
{
public virtual object Obj{get;set;}
public Parent()
{
// Re-sharper warning: this is open to change from
// inheriting class overriding virtual member
this.Obj = new Object();
}
}
The child class here overrides the parent property. If this property was not marked virtual the compiler would warn that the property hides property on the parent class and suggest that you add 'new' keyword if it is intentional.
public class Child: Parent
{
public Child():base()
{
this.Obj = "Something";
}
public override object Obj{get;set;}
}
Finally the impact on use, the output of the example below abandons the initial value set by parent class constructor.
And this is what Re-sharper attempts to to warn you, values set on the Parent class constructor are open to be overwritten by the child class constructor which is called right after the parent class constructor.
public class Program
{
public static void Main()
{
var child = new Child();
// anything that is done on parent virtual member is destroyed
Console.WriteLine(child.Obj);
// Output: "Something"
}
}
Beware of blindly following Resharper's advice and making the class sealed!
If it's a model in EF Code First it will remove the virtual keyword and that would disable lazy loading of it's relationships.
public **virtual** User User{ get; set; }
There's a difference between C++ and C# in this specific case.
In C++ the object is not initialized and therefore it is unsafe to call a virutal function inside a constructor.
In C# when a class object is created all its members are zero initialized. It is possible to call a virtual function in the constructor but if you'll might access members that are still zero. If you don't need to access members it is quite safe to call a virtual function in C#.
Just to add my thoughts. If you always initialize the private field when define it, this problem should be avoid. At least below code works like a charm:
class Parent
{
public Parent()
{
DoSomething();
}
protected virtual void DoSomething()
{
}
}
class Child : Parent
{
private string foo = "HELLO";
public Child() { /*Originally foo initialized here. Removed.*/ }
protected override void DoSomething()
{
Console.WriteLine(foo.ToLower());
}
}
I think that ignoring the warning might be legitimate if you want to give the child class the ability to set or override a property that the parent constructor will use right away:
internal class Parent
{
public Parent()
{
Console.WriteLine("Parent ctor");
Console.WriteLine(Something);
}
protected virtual string Something { get; } = "Parent";
}
internal class Child : Parent
{
public Child()
{
Console.WriteLine("Child ctor");
Console.WriteLine(Something);
}
protected override string Something { get; } = "Child";
}
The risk here would be for the child class to set the property from its constructor in which case the change in the value would occur after the base class constructor has been called.
My use case is that I want the child class to provide a specific value or a utility class such as a converter and I don't want to have to call an initialization method on the base.
The output of the above when instantiating the child class is:
Parent ctor
Child
Child ctor
Child
I would just add an Initialize() method to the base class and then call that from derived constructors. That method will call any virtual/abstract methods/properties AFTER all of the constructors have been executed :)
Another interesting thing I found is that the ReSharper error can be 'satisfied' by doing something like below which is dumb to me. However, as mentioned by many earlier, it still is not a good idea to call virtual properties/methods in constructor.
public class ConfigManager
{
public virtual int MyPropOne { get; private set; }
public virtual string MyPropTwo { get; private set; }
public ConfigManager()
{
Setup();
}
private void Setup()
{
MyPropOne = 1;
MyPropTwo = "test";
}
}
I want to write a framework which needs to implement a few functions. Now I need to access the base class functions from the framework, which does not work.
I need to inherit form a given class "Master"
public class MyClass : Master
{
protected override void Initialize() {
FunctionInMaster();
VariableInMaster = true;
}
}
Now I simply want to create a class that can be derived and implements Master functions.
public class MyFrameworkClass
{
// framework override
public void whatever()
{
FunctionInMaster();
VariableInMaster = true;
}
}
public class MyClass : Master
{
protected override void Initialize() {
whatever();
FunctionInMaster();
VariableInMaster = true;
}
}
How do I do that without instantiating "MyFrameworkClass" and passing a pointer of "this" to MyFrameworkClass?
You can never have multiple inheritance in C# (and it's a very good thing, multiple inheritance is a nightmare), but you can invoke methods from other classes, or even have some composition.
public static class MyFrameworkClass
{
// framework override
public static void whatever(Master master)
{
master.FunctionInMaster();
master.VariableInMaster = true;
}
}
public class MyClass : Master
{
protected override void Initialize()
{
MyFrameWorkClass.whatever(this);
FunctionInMaster();
VariableInMaster = true;
}
}
Don't try to do too many things with inheritance. Inheritance is a powerful tool, but not an universal one. Often composition is better suited to tackle a specific problem.
You could also have multiple levels of inheritance, if you need to access protected methods and you know you will reuse this code in other derived classes.
public class MyFrameworkClass : Master
{
// framework override
protected void whatever()
{
FunctionInMaster();
VariableInMaster = true;
}
}
public class MyClass : MyFrameworkClass
{
protected override void Initialize()
{
whatever();
FunctionInMaster();
VariableInMaster = true;
}
}
Although you could change inheritance to be Master -> MyFrameworks -> MyClass, that is less advisable. Is the intention to make sure deriving classes implement specific methods - in that case consider adding abstract methods to Master. If you are unable to alter Master, you can change MyFrameworks to be an interface rather than a class. MyClass can inherit multiple interfaces, but only one class.
I need to access the base class [instance] functions from the framework
To call instance methods you need an instance. There are three ways to do that:
Inherit form the class and use this - you have already stated that you can't do this.
Accept an instance of the base class and call methods on it - you have stated that you don't want to do this.
Create an instance of the class and call methods on it.
Now static methods are different - you do not need an instance, but they can only use static fields, which would be shared across all instances of the class. Since you use a non-static property in the base class, it's safe to assume that static is not an option, so you're stuck with one of the three options above.
I was trying few things and would like to know why this is happening so.
Say, I have a class called A in namespace n and I was trying to create protected internal class B.
namespace n
{
public class A
{
public A()
{
}
}
protected internal class B //throwing error
{
}
}
But when i try like this (B as a sub class of A), its not throwing error and its built success. Could you explain me why it is so?
namespace n
{
public class A
{
public A()
{
}
protected internal class B // its not throwing error
{
}
}
}
Am i missing anything theoretically? Its quite a bit confusing.
A class can't be protected except when it is inside another class.
The protected keyword is only valid for members of a class. In your second example, class B happens to be that member.
Think about it:
protected means: Derived classes can access this member.
As there is no such concept as derived namespaces, the protected keyword doesn't make sense for members of a namespace.
Look at the error.
Elements defined in a namespace cannot be explicitly declared as
private, protected, or protected internal
Only internal or public members are allowed outside the class.
Your second case is defining the class B as member of class A that is why you are not getting the error.
You may see Access Modifiers C#
Classes and structs that are declared directly within a namespace (in
other words, that are not nested within other classes or structs) can
be either public or internal. Internal is the default if no access
modifier is specified.
protected declares visiblity level for derived types.
In your first case you declare class inside namespace. There is no any polymophic support for namespaces, so there is no any sence of using protected classes in namespace
In second case, instead, you use it inside other classe (class A), which make it visible for all children of A class.
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.
Ok, let's leave the debate of whether friendship breaks encapsulation, and actually try elegantly come up with a coherent design. It is a two fold function:
1) General question on how to implement:
public class A
{
friend class B;
}
2) Why do I need this functionality? Some of my classes implement ISerializable interface. However, I want to make ISerializable methods protected in the Derived class so that I don't expose them to a client (as well as in the documentation). However, internal classes should be able to access them. What is the General way to solve this problem in C#?
Note: I am using friendship as defined in the current C++ standard.
Thanks
C# has the internal keyword, so that other types in the same assembly see the types marked internal. Additionally, you can add attributes to the assembly to allow types outside of the assembly to see that assembly's internal members.
If the classes are in the same assembly you can use internal. If they're in different assemblies you can use the friend assembly attribute.
Leaving the InternalsVisibleTo stuff to one side, you only have two choices when it comes to implementing interfaces:
Implement them with public methods
Implement them using explicit interface implementation
In both cases anyone can call the methods, but using explicit interface implementation you can only call the methods "via" an interface expression (e.g. you could cast a variable of the actual type to the ISerializable).
There's no such concept as "internally" implementing an interface.
internal members are public within the current .dll and private externally. Additionally, you can expose them to external .dll's by using the InternalsVisibleTo attribute.
I have several solutions, that all revolve around using a private singleton instance as a "key" to prove that the caller is who they say they are.
Solution 1: friend class is a singleton
public class A
{
private underwear myUnderwear;
public ChangeUnderwear(B friend, underwear newUnderwear)
{
if (friend == null) return;
myUnderwear = newUnderwear
}
}
public sealed class B
{
private B() {};
private B inst;
private MessWithA(A a)
{
a.ChangeUnderwear(this, new Thong());
}
}
Does anyone see any flaw there? That technique would work for when you have a Foo class and a FooManager singleton.
Solution 2:
If the friend is not a singleton, I guess you could use the same idea of hiding construction and hiding all instances:
interface IB
{ ... }
public sealed class B : IB
{
private B() {};
public IB CreateB()
{
return (IB)new B();
}
private MessWithA(A a)
{
a.ChangeUnderwear(this, new Thong());
}
}
But now you now you need some way to prevent an enemy from simply casting IB to a B, and then impersonating a B to access A's friend only members. Any ideas?
Solution 3: the singleton class lets it's instance be owned by the first caller who requests it. The friend class tries to grab the instance on startup, and throws a tantrum if someone else grabs it first
public class A
{
private underwear myUnderwear;
public ChangeUnderwear(B.IdCard friend, underwear newUnderwear)
{
if (friend == null) return;
myUnderwear = newUnderwear
}
}
public class B
{
public sealed class IdCard
{
private IdCard() {};
private static bool created = false;
public IDCard GetId()
{
if (created) throw new Exception("Why are two people asking for the same ID?!?");
created = true;
return new IDCard();
}
}
private static IdCard id;
static B()
{
id = IDCard.CreateId();
if (id == false) throw new Tantrum("Panic: Someone stole my ID card before I could grab it");
}
private void MessWithA(A a)
{
a.ChangeUnderwear(id, new Thong());
}
}