This question already has answers here:
How to make a property protected AND internal in C#?
(8 answers)
Closed 7 years ago.
Consider the following classes:
public class Vehicle { ... }
public class Coverage { ... }
public class VehicleList : IEnumerable<Vehicle> { ... }
public class CoverageList : IEnumerable<Coverage> { ... }
public abstract class Quote
{
protected VehicleList vehicles;
protected CoverageList coverages;
internal Quote() { ... }
public IReadOnlyCollection<Vehicle> Vehicles
{
get { return this.vehicles.AsReadOnly(); }
}
public IReadOnlyCollection<Coverage> Coverages
{
get { return this.coverages.AsReadOnly(); }
}
...
}
public sealed class OhQuote : Quote
{
//needs to access protected fields
...
}
public sealed class InQuote : Quote { ... }
public sealed class MiQuote : Quote { ... }
Quote fully encapsulates the functionality of both VehicleList and CoverageList so I'd like to mark those classes as internal. The problem is that they are the types of protected fields of a public class. If I mark those fields as protected internal then they are protected OR internal. What I really need is for them to be protected AND internal (with protected taking precedence within the assembly). You can see that neither Quote (which has an internal constructor) nor its subclasses (which are sealed) can be extended outside the assembly. I've already figured out how to achieve the desired functionality using public interfaces but wanted to make sure there's not a more concise way.
Although the .NET runtime supports this concept ("FamilyAndAssembly"), C# currently does not.
This was proposed for C# 6.0 in the form of the private protected access modifier, but the feature was dropped.
UPDATE: private protected was added to C# 7.2.
As an addendum:
If you want not to use interfaces and -as you see- there is no C# support to achieve that goal, remember: you can always use reflection to do very weird and strange things like that.
You can set the field to private and using reflection you can assign new values from wherever you want, for sure from derived classes in same assembly.
I question the need for your derived classes to access Quote's fields directly.
I am asking if there is a way to achieve the desired functionality without using public interfaces.
I think you can safely change the modifiers on the fields to private and have the derived classes manipulate the fields indirectly through protected methods defined in your Quote base class. No additional public interfaces would be required.
Here is an example of what it could look like:
public class Vehicle {}
public class Coverage {}
// Set these as "internal" as you were hoping for...
internal class VehicleList : IEnumerable<Vehicle>
{
public void Foo() {}
}
internal class CoverageList : IEnumerable<Coverage>
{
public void Bar() {}
}
public abstract class Quote
{
// Mark these as "private"
private VehicleList vehicles;
private CoverageList coverages;
internal Quote() {}
public IReadOnlyCollection<Vehicle> Vehicles
{
get { return this.vehicles.AsReadOnly(); }
}
public IReadOnlyCollection<Coverage> Coverages
{
get { return this.coverages.AsReadOnly(); }
}
// Add protected methods to manipulate the private fields.
protected void PerformFooOnVehicles()
{
this.vehicles.Foo();
}
protected void PerformBarOnCoverages()
{
this.coverages.Bar();
}
}
public sealed class OhQuote : Quote
{
// We now have indirect access to Quote's private fields.
public void Baz()
{
this.PerformBarOnCoverages();
this.PerformFooOnVehicles();
}
}
public sealed class InQuote : Quote {}
public sealed class MiQuote : Quote {}
This alternative accomplishes the goal of indirectly exposing VehicleList and CoverageList only to derived classes that are part of the same assembly.
Related
I want to access a property of some class of mine, but get compiler error "CS0572 - Cannot reference a type through an expression".
I have the following setup
public interface IHelper {
void DoHelp();
}
public abstract class ClassWithHelperBase<THelper> where THelper : IHelper {
public THelper Helper { get; }
}
public class ClassWithHelper : ClassWithHelperBase<ClassWithHelper.Helper> {
// use a nested class, since there will be n classes deriving from ClassWithHelper and giving each helper a readable name (in this example ClassWithHelperHelper) is ugly
public class Helper : IHelper {
public static void SomeStaticMethod() { }
public void DoHelp() { }
}
}
public class Test {
private ClassWithHelper myClass;
public void DoTest() {
((ClassWithHelperBase<ClassWithHelper.Helper>) myClass).Helper.DoHelp(); // this works, but is ugly
myClass.Helper.DoHelp(); // what I want, but it's not working
//myClass.Helper.SomeStaticMethod(); // funnily IDE supposes static methods here even though the resulting code is invalid, since I am (obviously) not referencing the class type
}
}
The interface is unnecessary for reproduction, I added it for clarity.
Note: I do not want to call a static method, I just added it, to show the IDE mixes up the member and the class qualifier.
Is there a way to access the property Helper of myClass, without casting myClass or renaming the nested class?
Aka: Why can't the compiler distinguish the member and the nested class?
The problems is due to name collision between Helper class (type) and Helper property. Try this
public interface IHelper
{
void DoHelp();
}
public abstract class ClassWithHelperBase<THelper> where THelper : IHelper
{
public THelper Helper { get; set; }
}
public class ClassWithHelper : ClassWithHelperBase<ClassWithHelper.CHelper>
{
// use a nested class, since there will be n classes deriving from ClassWithHelper and giving each helper a readable name (in this example ClassWithHelperHelper) is ugly
public class CHelper : IHelper
{
public static void SomeStaticMethod() {}
public void DoHelp() { }
}
}
public class Test
{
private ClassWithHelper myClass;
public void DoTest() {
myClass.Helper.DoHelp();
ClassWithHelper.CHelper.SomeStaticMethod();
}
}
Here I renamed Helper class to the CHelper, so compiler can now distinguish class and property and thus the line myClass.Helper.DoHelp(); now works without cast.
If a "do not rename nested class" requirement is absolutely mandatory, then the problem may be also solved by renaming the Helper property in the base class to avoid name collision. However, I can't imagine better name for the property.
Unfortunately, for the static method, you can't reference myClass instance. So, you will need reference the whole type.
According to object oriented principles, we can define any class in any namespace as private or protected but when I create a class as private or protected I get the following compilation error:
Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal
namespace test
{
public class A
{
public A()
{
}
}
protected class B //throwing error
{
}
}
I searched for a solution and I found the following on Stack Overflow:
Anything that is not a member of an enclosing type (class) doesn't make sense at all to be protected.
Why can't I declare B as protected?
I guess I don't understand what protected means. What does it mean?
Only nested classes can be marked as protected.
namespace test
{
public class A
{
public A() { }
protected class B
{
public B() { }
}
}
}
Protected says that the class can only be used inside the class it is specified in or inherited from. Therefore it does not make sense to declare a protected class in a namespace. What would this mean? Protected can only be applied to nested classes therefore.
In C# you cannot declare classes as protected, except when they are nested within other classes:
namespace test
{
public class A
{
public A()
{
}
protected class B // nested class
{
}
}
}
This makes sense because protected means that it should only be accessible by the enclosing class or a class derived from that enclosing class.
If it is ok if class B can be accessed by all classes in the same assembly but not from outside, you can declare the class as internal:
namespace test
{
public class A
{
public A()
{
}
}
internal class B // accessible within same assembly
{
}
}
Im not sure if it is possible. I am running into a unique issue dealing with a clients api.
I am needing to extend a class and add a bool property that does not exist in the base class.
below is an example of what I am trying to accomplish.
public class baseClass
{
//.. No Editable Access
}
public class Extended
{
public bool flaggedAsDeleted(this baseClass bc)
{
//Idealy was looking for get; set; but I know that don't work
return true;// Need to know if possible to set property on baseClass or Alternative
}
public void flagAsDeleted(this baseClass bc)
{
flaggedAsDeleted = true;
}
}
public class program
{
public void doit()
{
baseClass bc = new baseClass();
bc.flagAsDeleted();
}
}
If you're trying to actually extend a class, you do it like this:
public class BaseClass
{
//.. No Editable Access
}
public class Extended : BaseClass
{
public bool FlaggedAsDeleted { get; set; }
}
If you're trying to add data to an existing class, you have two options:
Inheritance - as seen above.
Encapsulation - create a new object that holds an instance of the type you're adding to.
C# provides a feature called Extension Methods, which allows you to seemingly add methods to existing classes. However, these are really just syntactic sugar, as you're still constrained to the class's public API.
public class BaseClass
{
public int Value { get; set; }
}
public static class ExtensionMethods
{
public static void Increment(this BaseClass b)
{
b.Value += 1;
}
}
Extension methods do not allow you to add data to an existing class though.
This is not unique. This is a common problem solved using a Design Pattern called decorator.
Here is an example. I have two classes, one inherited, and both have a function with the same name, but different arguments:
public class MyClass
{
//public class members
public MyClass()
{
//constructor code
}
public void Copy(MyClass classToCopy)
{
//copy code
}
}
public class InheritedClass : MyClass
{
//public class members
public InheritedClass():base()
{
//constructor code
}
public void Copy(InheritedClass inheritedClassToCopy)
{
//copy code
}
}
My question is how do I make the base class' copy method (MyClass.Copy) non-inheritable or non-visible in InheritedClass? I don't want to be able to do this:
MyClass a;
InheritedClass b;
b.Copy(a);
Does this make sense, or should I keep this functionality in there? Can what I'm asking even be done?
Does this make sense, or should I keep this functionality in there? Can what I'm asking even be done?
Trying to hide a public method like this when used by a base class is problematic. You're purposely trying to violate the Liskov substitution principle.
You can't do what you are wanting to do here; C# does not allow negative variance in inherited members. (almost no languages truly do, actually)
It may be that you don't want an inherited class here at all, though; what you may really want is an interface. Or... your two classes here may not have the correct relationship; perhaps they should both instead be common siblings of a third class, which is their parent.
You can use explicit interface implementation to hide this method from the inheritor. But you will need to add an interface of course and you will need to cast your type to the interface to call your method:
public interface MyInterface
{
void Copy(MyClass classToCopy)
}
public class MyClass : MyInterface
{
void MyInterface.Copy(MyClass classToCopy)
{
//copy code
}
}
This is not possible. An inherited class inherits all public and protected members, methods and properties. Using the sealed modifier with make it non-overridable, but still accessible to your inherited class.
What everyone else said, but if I am inferring your goal correctly, it is to make sure that InheritedClass users never use the MyClass method. In that case, exclude it from MyClass and make two classes that inherit it.
Make MyBaseClass abstract if it should not be instantiated (most likely).
(Edited -- you probably would want to include copy code for anything that's part of the base class in the base class)
public abstract class MyBaseClass
{
public MyClass()
{
//constructor code
}
protected void Copy(MyBaseClass classToCopy)
{
//copy code
}
// other methods that all inherited classes can use
}
public class MyClass: MyBaseClass
{
public MyClass():base()
{
//constructor code
}
public void Copy(MyClass myClassToCopy)
{
base.Copy(myClassToCopy);
//specific copy code for this extensions in this class
}
}
public class InheritedClass : MyBaseClass
{
public InheritedClass():base()
{
//constructor code
}
public void Copy(InheritedClass inheritedClassToCopy)
{
base.Copy(myClassToCopy);
//specific copy code for this extensions in this class
}
}
How do you declare a method in C# that should be overridden (or overridable) by a dereived class - possibly even outside your assembly - but that should be callable only from within the actual class?
(i.e. like a private virtual function in C++)
[edit]
private virtual is exactly what I intend: "Here's a way to modify my behavior, but you are still not allowed to call this function directly (because calling it requires arcane invocations that only my base class shall do)"
So to clarify it: what is the best expression for that in C#?
When you say it should only be callable "within the actual class" do you mean the base class or the derived class? Neither of these is feasible on its own. The closest is to use a protected method, which means it can be called from the declaring class, the derived class, and any further-derived class.
C# makes a stronger guarantee for "private" than C++ does. In C++, you can indeed override a private virtual method. But that means that code in a base class can execute code in a derived class. Breaking the promise that the private method is truly private and can only be called by methods in the same class.
Something that doesn't help here is that C++ doesn't require repeating the virtual keyword. Leading up to hard to reverse-engineer mysteries like this one:
#include "stdafx.h"
#include <iostream>
class Base {
private:
virtual void Method() = 0;
public:
void Test() {
Method();
}
};
class Derived : public Base {
private:
void Method() { std::cout << "Who the heck called me?"; }
};
int _tmain(int argc, _TCHAR* argv[])
{
Base* p = new Derived;
p->Test();
}
I agree there's a possible role for private inheritance. The C# language designers said No! though.
A private member is not visible to child classes. I think protected virtual will perform the way you'd like?
UPDATE:
Here in greater detail is an explaination of what you can do with inheritance and overriding functions within C#. I tried to use a somewhat meaningful example, but consider it understood that its a poor class design and I wouldn't ever recommend implementing the classes described in this way. However, I hope perhaps this will give you an avenue to approach solving your original problem in a manner that might be acceptable. There is no way to prevent a concrete class from calling any of its members, but if your structure is like this in anyway, perhaps its not issue.
public abstract class Animal
{
public void DisplayAttributes()
{
Console.WriteLine(Header());
Console.WriteLine("Name: " + Name());
Console.WriteLine("Legs: " + Legs());
Console.WriteLine();
}
protected virtual int Legs()
{
return 4;
}
private string Header()
{
return "Displaying Animal Attributes";
}
protected abstract string Name();
}
public class Bird : Animal
{
protected override string Name()
{
return "Bird";
}
protected override int Legs()
{
return 2;
}
}
public class Zebra : Animal
{
protected override string Name()
{
return "Zebra";
}
}
public class Fish : Animal
{
protected override string Name()
{
return "Fish";
}
protected override int Legs()
{
return 0;
}
private string Header()
{
return "Displaying Fish Attributes";
}
protected virtual int Gils()
{
return 2;
}
public new void DisplayAttributes()
{
Console.WriteLine(Header());
Console.WriteLine("Name: " + Name());
Console.WriteLine("Gils: " + Gils());
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
Bird bird = new Bird();
bird.DisplayAttributes();
//Displaying Animal Attributes
//Name: Bird
//Legs: 2
Zebra zebra = new Zebra();
zebra.DisplayAttributes();
//Displaying Animal Attributes
//Name: Zebra
//Legs: 4
Fish fish = new Fish();
fish.DisplayAttributes();
//Displaying Fish Attributes
//Name: Fish
//Gils: 2
List<Animal> animalCollection = new List<Animal>();
animalCollection.Add(bird);
animalCollection.Add(zebra);
animalCollection.Add(fish);
foreach (Animal animal in animalCollection)
{
animal.DisplayAttributes();
//Displaying Animal Attributes
//Name: Bird
//Legs: 2
//Displaying Animal Attributes
//Name: Zebra
//Legs: 4
//Displaying Animal Attributes
//Name: Fish
//Legs: 0
//*Note the difference here
//Inheritted member cannot override the
//base class functionality of a non-virtual member
}
}
}
In this example, Bird, Zebra, and Fish could all call their Name and Legs methods, but within the context if this example, there wouldn't necessarily be utility in doing so. Additionally, as shown by Fish, the DisplayAttributes() can be modified for an instance of a concrete derived class; but when you're looking at an Animal, as in the foreach loop, you get the base classes DisplayAttributes behavior, regardless of the actual type of animal. I hope this may help povide the type of functionality you would like to replicate.
Here's an example of what vboctor has already mentioned:
public class Base
{
private Func<Base, int> func;
protected void SetFunc(Func<Base, int> func)
{
this.func = func;
}
private void CallFunc()
{
if (func != null)
{
var i = func(this);
}
}
}
public class Sub : Base
{
private void DoFuncyStuff()
{
this.SetFunc(b => 42);
}
}
Did you consider the use of a delegate to do that? You can allow the derived class to set the delegate via some protected property or passing it to your constructor. You can also default the delegate to your internal implementation which is a private method on your base class.
Why do you need it to be private? Protected should be sufficient, here. You're asking the subclass author to write code that they can't call. What does this accomplish? They could use that code anyway.
As I read your question, you could mean two things.
First ,if if you want a function in Class A that can be overriden in Child Class B but is not visible to any outside class:
public class ClassA
{
protected virtual ReturnType FunctionName(...) { ... }
}
public class ClassB
{
protected override ReturnType FunctionName(...) { ... }
}
Second, if you want to force an implementing class to define the function:
public abstract class ClassA
{
protected abstract ReturnType FunctionName(...);
}
public class ClassB
{
protected override ReturnType FunctionName(...) { ... }
}
Another concept you might look at if you are just digging into C# that is kinda related is partial classes. This is the idea of two source files being combined at compile time to create one class, both from the same assembly:
File 1:
public partial class ClassA
{
private ReturnType FunctionName(...);
}
File 2:
public partial class ClassA
{
//actual implimentation
private ReturnType FunctionName(...){ ... };
}
Partials are not widely used except when dealing with designed-generated files, like the Linq2Sql files, or EDM, or WinForms, etc.
Guess this will not work out as you intended, but let me sketch some pseudo-code for you:
public interface BaseClassFunction {
void PleaseCallMe();
}
public class BaseClass {
private BaseClassFunction fn;
public BaseClass(BaseClassFunction fn) {
this.fn = fn;
}
private CallMe() {
fn.PleaseCallMe();
}
public PublicCallMe() {
CallMe();
}
}
private class DerivedClassFunction : BaseClassFunction {
void PleaseCallMe() { ... do something important ... }
}
public class DerivedClassFunction {
public DerivedClassFunction() : BaseClass(new DerivedClassFunction()) {
}
}