Internal parameter for Protected method on Public Abstract class [duplicate] - c#

This question is similar to c# internal abstract class, how to hide usage outside but my motiviation is different. Here is the scenario
I started with the following:
internal class InternalTypeA {...}
public class PublicClass
{
private readonly InternalTypeA _fieldA;
...
}
The above compiles fine. But then I decided that I should extract a base class and tried to write the following:
public abstract class PublicBaseClass
{
protected readonly InternalTypeA _fieldA;
...
}
And thus the problem, the protected member is visible outside the assembly but is of an internal type, so it won't compile.
The issue at hand is how to I (or can I?) tell the compiler that only public classes in the same assembly as PublicBaseClass may inherit from it and therefore _fieldA will not be expossed outside of the assembly?
Or is there another way to do what I want to do, have a public super class and a set of public base classes that are all in the same assembly and use internal types from that assembly in their common ("protected") code?
The only idea I have had so far is the following:
public abstract class PublicBaseClass
{
private readonly InternalTypeA _fieldA;
protected object FieldA { get { return _fieldA; } }
...
}
public class SubClass1 : PublicBaseClass
{
private InternalTypeA _fieldA { get { return (InternalTypeA)FieldA; } }
}
public class SubClass2 : PublicBaseClass
{
private InternalTypeA _fieldA { get { return (InternalTypeA)FieldA; } }
}
But that is UGLY!

The CLR provides a FamilyAndAssembly accessibility which will do what you want, but there isn't the syntax in C# to use it.
The workaround is to make the variable field internal, and you'll have to trust the code in your assembly to not access it inappropriately.
You can also make the constructor of PublicBaseClass internal, so only your assembly can instantiate it. That way, only your classes can inherit off it (even if the class itself is public)

The cleanest way to deal with this is the use of public interfaces and private classes. If your refactoring existing code this is not always an option. One easy way to ease the pain of that conversion is to use a public abstract class instead of an interface and expose a static factory method.
Example:
public abstract class MyClass
{
public static MyClass New()
{ return new InternalMyClass(); }
}
class InternalMyClass : MyClass
{ }

Related

Best way to handle a derived class with a method not shared by any other derived class without adding it to the base class?

I am currently refactoring some code and am dealing with reorganizing a collection of about a dozen classes with some common methods into a set of derived classes with the shared code in the base, which implements an interface exposing the methods. So far the new structure is fairly straightforward and can be summarised as follows:
public interface IContract
{
public bool MethodA();
}
public abstract class BaseClass : IContract
{
// Default implementation
public virtual bool MethodA() { return true; }
}
public class DerivedClassA : BaseClass
{
private readonly SomeServiceA service;
// Class-specific implementation (if required)
public override bool MethodA() { return service.CheckA(); }
}
Problem is that there is one derived class that contains a public method shared by no other derived class:
public class DerivedClassB : BaseClass
{
private readonly SomeServiceB service;
public override bool MethodA() { return service.CheckB(); }
public void MethodB() { service.PerformAnotherAction(); }
}
This method is currently invoked elsewhere in the codebase as below:
// Factory initialises a class of a type specified in config settings
IContract instance = ClassFactory.GetInstance();
bool ClientMethodA()
{
return instance.MethodA();
}
void ClientMethodB()
{
if (instance.GetType() == typeof(DerivedClassB))
{
((DerivedClassB)instance).MethodB();
}
}
I'd rather the invoking code not know anything about DerivedClassB but I'm not sure how to avoid the casting. My question is whether this design structure is the most optimal given this workflow, and if not, how could it be improved while adhering to SOLID principles?

C#: Protected Variables inside of a Generic Class can be accessed by a different subclass of that Generic Class. Can I prevent this?

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

Class is Private and members are Public what its scope?

If class declare as a Private and its Members are Public so what is the accessibility of related class?
If your private class implements some interface you can access to public methods via the interface. Here's piece of code:
public interface ITest
{
void Test();
}
public class Program
{
public static void Main()
{
ITest nestedProgram = new NestedProgram();
AnyOtherClass otherClass = new AnyOtherClass();
otherClass.AnyMethod(nestedProgram);
}
private class NestedProgram : ITest
{
public void Test()
{
Console.WriteLine("Test method invoked");
}
}
}
public class AnyOtherClass
{
// won't compile
// public void AnyMethod(Program.NestedProgram test)
public void AnyMethod(ITest test)
{
// won't compile
//ITest nestedProgram = new Program.NestedProgram();
test.Test();
}
}
The class is what you declare it as. The "private" modifier on the class declaration matters on nested classes, but there's nothing to stop the class its nested in using its public members. I would argue that the two aren't particularly related because their goals are slightly different (one is the visibility of the class itself for instantiation and where it can be referenced, the other controls what members can be accessed).
Also consider this example:
public interface ITest
{
void TestMethod();
}
public static class TestFactory
{
private class Test: ITest
{
public void TestMethod() { }
}
public static ITest CreateTest()
{
return new Test();
}
}
Examples:
TestFactory.Test a = new TestFactory.Test(); // doesn't work because the class is private
TestFactory.Test b = null; // also doesn't work because the class is private
ITest c = null; // works, the interface is public
ITest d = TestFactory.CreateTest(); // works, because the interface is public and CreateTest is declared to return the interface.
In this example, only TestFactory can see the class to create an instance of it. On the other hand, the return value is the public interface, which states that implementers should have a public method TestMethod();
In this situation, the method has to be public. Although only TestFactory can directly instantiate and see the class, it can still be exposed through an interface (or base class).
Anyway, it's probably best to take a look at the docs.
Access modifiers are keywords used to specify the declared accessibility of a member or a type.
public modifier
The public keyword is an access modifier for types and type members. Public access is the most permissive access level.
There are no restrictions on accessing public members.
Accessibility
Can be accessed by objects of the class
Can be accessed by derived classes
Private access is the least permissive access level.
Private members are accessible only within the body of the class or the struct in which they are declared.
Accessibility
Cannot be accessed by object.
Cannot be accessed by derived classes.
Now lets come to the exact answer if the class is declared as private and its members are public then accessibility level of members will stay within class because private class can't be inherited.

Accessing internal methods through a public interface [duplicate]

This question already has answers here:
How to Mock the Internal Method of a class?
(6 answers)
Closed 4 years ago.
The Situation
Suppose I have a class with an internal method:
class MyClass : IMyClass
{
public void PublicMethod() { ... }
internal void InternalMethod() { ... }
}
that implements an interface:
interface IMyClass
{
void PublicMethod() { ... }
}
And a container class that holds an instance of MyClass and other concrete classes:
class ContainerClass
{
public MyClass myClass;
...
}
ContainerClass is used by various assemblies. When used within the same assembly as MyClass the calling method can invoke containerClass.myClass.InternalMethod()
The Problem
In an effort to make things more easily mockable for testing, I am now trying to replace the ContainerClass's properties with interfaces rather than concrete classes, e.g.:
class ContainerClass
{
public IMyClass myClass;
...
}
But, if I do that, InternalMethod can no longer be invoked using containerClass.myClass.InternalMethod() because the method doesn't exist on the interface... nor can it, because it is internal. However, I cannot make the interface internal because ContainerClass is used by other assemblies as well.
Let's assume that I cannot change the internal access to that method. Is there another way?
EDIT: This is different from How to Mock the Internal Method of a class? because I am not trying to mock the internal method, I am trying to keep it exposed when replacing a concrete class (MyClass) with an interface (IMyClass).
An option is to create two interfaces, one public and one internal:
public interface IMyClassPublic
{
void PublicMethod();
}
internal interface IMyClassInternal
{
void InternalMethod();
}
Implement both of them in MyClass (you need to implement IMyClassInternal explicitly since it's internal):
public class MyClass : IMyClassPublic, IMyClassInternal
{
public void PublicMethod() { }
void IMyClassInternal.InternalMethod() { }
}
And change ContainerClass so that it exposes both interfaces separately (and probably make myClass private):
public class ContainerClass
{
private MyClass myClass;
public IMyClassPublic myClassPublic
{
get
{
return myClass;
}
}
internal IMyClassInternal myClassInternal
{
get
{
return myClass;
}
}
}
Now you can mock both of them, use the internal method as containerClass.myClassInternal.InternalMethod() and the public method as containerClass.myClassPublic.PublicMethod().

Is there a good way to handle private static fields in a generic type in C#?

I am trying to figure out a way I can make use of private static fields in a generic class. This is the obvious way to do it (fiddle). It won't compile because Field is not accessible in BaseChild, and ideally I wouldn't want it to be accessible there:
public class Base<T>
{
private static readonly string Field = "field";
public Base()
{
Console.WriteLine(Field);
}
}
public class BaseChild : Base<string>
{
public BaseChild()
{
Console.WriteLine(Field);
}
}
The problem with this solution is that there is a different Field for each generic type, instead of being shared across them.
I have seen this answer where it says that JetBrains recommends a solution for static fields across generic types:
If you need to have a static field shared between instances with different generic arguments, define a non-generic base class to store your static members, then set your generic type to inherit from this type.
This makes sense for the case where you have public or protected static fields in the base class that you want to share across any child class like this example (fiddle):
public abstract class Base
{
protected static readonly string Field = "field";
}
public class Base<T> : Base
{
public Base()
{
Console.WriteLine(Field);
}
}
public class BaseChild : Base<string>
{
public BaseChild()
{
Console.WriteLine(Field);
}
}
However, what about the case where you want to use a private static field? I would guess that this is not possible since private means only accessible to the class it's declared in and I think that since the generic class is really just a template to create a class, that any private field could only ever be shared by each class, not across all the classes created by the template.
Do I have to just put the private field in the generic class (example 1) and accept it as at least a workable solution for what I want, or is there another way I can accomplish this?
First off -- private is doing exactly what it's made to do: to restrict access to only the type it was declared in. Keep in mind that instantiations of a generic type are all distinct types. You shouldn't be wanting to work around this.
If I understand your question correctly, you can accomplish what you want by using protected with an extra level of inheritance:
class EvenMoreBase
{
protected static readonly string Field = "field";
}
class Base<T> : EvenMoreBase
{
public Base()
{
Console.WriteLine(Field);
}
}
class BaseChild : Base<string>
{
public BaseChild()
{
Console.WriteLine(Field);
}
}
Now each of your Base<T> will share the same instance of Field.
You're correct in your thoughts on private within the base class. Whether it is static or not makes no difference.
Here's a little example:
using System;
public class Program
{
public static void Main()
{
Bar b = new Bar(); // Prints "Foo"
// Console.WriteLine(Foo.BaseField); // Compile error
}
}
public class Foo
{
protected static readonly string BaseeField = "Foo";
}
public class Bar : Foo
{
public Bar()
{
Console.WriteLine(Foo.BaseeField);
}
}
Marking it protected is useful, if you'd like only your children to be able to access it. And leaving it static is how you'd keep only one instance around for all children of the base Foo class.
This is something I came up with that I think actually does what I want better than the initial example I put in my question. It shares a single static field across all the generic types, and it is inaccessible from children of the Base generic class.
public static class Base
{
private static string Field = "field";
public class Base2<T>
{
public Base2()
{
// Field is accessible here, but is the same across all generic classes
Console.WriteLine(Field);
}
}
}
public class BaseChild : Base.Base2<string>
{
public BaseChild()
{
//Field is not accessible here, and I don't really want it to be
//Console.WriteLine(Field);
}
}

Categories