c# hide from dervied classes some properties of base class - c#

I want to know if its possible to hide a base class property from a derived class:
Example:
class BaseDocument
{
public string DocPath{get; set;}
public string DocContent{get; set;}
}
class DerviedDocument: BaseDocument
{
//this class should not get the DocContent property
public Test()
{
DerivedDocument d = new DerivedDocument();
d.//intellisense should only show me DocPath
//I do not want this class to see the DocContent property
}
}
I cannot make the DocContent property private, because I want to instantiate the BaseDocument class elsewhere and use the property there. That will kill the idea of a property anyway.
One way to fix this would be to use a interface, say IDoc, which exposes DocPath property and make both the BaseDocument and DerivedDocument implement the interface. This will break their parent-child relationship though.
I can play with the new and override keywords, but that's not the right way either because the child still 'sees' the property
I tried using the 'sealed' keyword on the DocContent, but that does not seem to solve the problem either.
I understand that it 'breaks' inheritance, but I guess this scenario should be coming up frequently where a child needs to get everything else from the parent but one or two properties.
How can such scenarios be handled gracefully?

I'm not sure inheritance would be the way to go here. Yes, you can hack around it by using the EditorBrowsableAttribute but I think the design should be rethought. One possible approach:
public interface IDoc
{
DocPath{get;set;}
}
class BaseDocument : IDoc
{
public DocPath{get; set;}
public DocContent{get; set;}
}
class DerviedDocument
{
public DerivedDocument(IDoc doc)
{
this.Doc = doc;
}
public IDoc Doc{get;set;}
public Test()
{
DerivedDocument d = new DerivedDocument(new BaseDocument());
d.//here you will only see d.IDoc which only exposes DocPath
}
}
Basically, use composition instead of inheritance, and program to an interface, not to an implementation.

You can do it easily if you don't mind having BaseDocument and DerivedDocument in different assemblies/projects.
Make DocContent internal. It'll be visible to everything in the same project as BaseDocument, but it won't be visible to DerivedDocument since that's in a different project. Of course, you'll need to make BaseDocument public (right now you have it as the default, internal).
In first project:
public class BaseDocument
{
public string DocPath {get; set;}
internal string DocContent {get; set;}
}
In second project that references first:
class DerivedDocument : FirstProject.BaseDocument
{
public Test()
{
DerivedDocument d = new DerivedDocument();
d. //intellisense shows DocPath, but not DocContent
}
}
This solution has the advantage of not being a kludge. You can still use BaseDocument's DocContent property within BaseDocument's project. If you need to use DocContent in another project (separate from the project DerivedDocument is in), you can use the InternalsVisibleTo attribute to make DocContent visible to that assembly. (That, however, is in my opinion a kludge, albeit a very handy one in some scenarios.)

It sounds like you want to intentionally violate the Liskov Substitution Principle. Why bother with subclassing at all if it's not going to have the conventional inheritance semantics? Just make a separate class.

interface IBaseDocument
{
string DocPath { get ; set ; }
string DocContent { get ; set ; }
}
class BaseDocument : IBaseDocument
{
public string DocPath { get ; set ; } // implement normally
private string MyDocContent ; // use this in BaseDocument
string IBaseDocument.DocContent // implement explicitly
{
get { return MyDocContent ; }
set { MyDocContent = value ; }
}
}
class DerviedDocument : BaseDocument
{
public void Test ()
{
// error: The name 'DocContent' does not exist in the current context
Console.WriteLine (DocContent) ;
}
}

A late reaction, but there are several ways to do this.
Most beautiful: Place your Base class in a separate assembly and mark the property DocContent as internal instead of public:
class BaseDocument
{
public string DocPath{get; set;}
internal string DocContent{get; set;} //won't be visible outside the assembly
}
Or use attributes to hide the property from the source editor:
class BaseDocument
{
public string DocPath{get; set;}
public string DocContent{get; set;}
}
class DerviedDocument: BaseDocument
{
//this class should not get the DocContent property
[Browsable(false), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public new string DocContent{ get; set; }
public Test()
{
DerivedDocument d = new DerivedDocument();
d.//intellisense will only show me DocPath
//I do not want this class to see the DocContent property
}
}

I don't believe there is a good (or any) way to do this. You may have to break the hierarchy, or you could remove the DocContent property from BaseDocument, then derive two sepearate classes from BaseDocument, one which is your current DerivedDocument, and another which has the DocContent property.

Just do this.
class BaseDocument
{
public DocPath{get; set;}
public virtual DocContent{get; set;}
}
class DerviedDocument: BaseDocument
{
public override DocContent
{
get { return null; }
set { }
}
}
Or
public override DocContent
{
get { throw new NotImplementedException("Do not use this property!"); }
set { throw new NotImplementedException("Do not use this property!"); }
}

Related

Unwanted setter of virtual string property, in derived class

Is there a better way of doing the following ...
I have a base class which provides a default implementation of the DisplayName property. Obviously optionally set, not required.
Edit: I can't use an interface instead of this base class, because I have behavior in it, which is trimmed out in this example.
public abstract class BaseObject
{
public virtual string DisplayName { get; protected set; }
public BaseObject(string displayName)
{
if (!string.IsNullOrWhiteSpace(displayName))
{
this.DisplayName = displayName.Trim();
}
}
// There is common behavior, unrelated to DisplayName here ... trimmed out of this sample code.
}
I have a system object class, derived from BaseObject, but providing its own implementation of DisplayName
public class SystemObject : BaseObject
{
public override string DisplayName
{
get
{
return string.Format("TODO: Resources.{0}", this.Id);
}
// EDIT: Turns out I can't even do that, because EF can't materialize the property. So, it needs to be an empty protected setter.
protected set { throw new InvalidOperationException("Do not set this property!"); }
}
public SystemObject() : base(null)
{
}
}
and I have a user-defined object, derived from the same base class:
public class UserObject : BaseObject
{
public UserObject(string displayName) : base(displayName)
{
if (string.IsNullOrWhiteSpace(displayName))
{
throw new ArgumentNullException("displayName");
}
}
public void ChangeDisplayName(string newDisplayName)
{
if (string.IsNullOrWhiteSpace(newDisplayName))
{
throw new ArgumentNullException("newDisplayName");
}
this.DisplayName = newDisplayName.Trim();
}
}
which utilizes the DisplayName from BaseObject to store a user-provided display name.
I can't make the DisplayName in BasObject abstract, because I am doing EF code first.
I am particularly concerned about protected set { throw new InvalidOperationException("Do not set this property!"); }. Any way to avoid this?
Don't use an abstract class at all when you don't actually want to define any behavior. If you just want a way of saying that there are different objects with a DisplayName property getter, then create an interface that defines such a contract that these two classes can implement in their own ways.
I think I see where you are going with this.
Leave the property alone. Just make it a get-only property in the base class, but make the getter call an abstract method:
public string DisplayName { get { return GetDisplayName(); } }
Then declare the method as abstract:
protected abstract string GetDisplayName();
That will force your inheriting classes to provide an implementation of how to return a display name. You can then change your UserObject class to store the name internally during instantiation and return it in the implementation of the method.
You could simply stub it out to do nothing;
public string DisplayName { set {} ...}

C# calling parent property while the child property is being called

I wanna see if there is anyway that when the child property method is being called, it will call the parent property as well.
Note that the child is generated by a code generator from edmx. So I can't change anything except adding a partial class for the child class. (It might be too trouble to change the generator.)
The situation I am having :
I have a class "MyClass" that is automatically generated from the database. I can't change anything on it except adding a partial class or change the code generator.
Now, I need to "do something" whenever the property Name is being called. I am thinking if I can put a parent there and make it call the parent to do "something" when the child property is "Name" is being called.
What I want :
public class ClassBase
{
public string Name
{
get
{
CallMethod();
return Name;
}
}
}
public class MyClass : ClassBase
{
public string Name { get; set; }
}
MyClass myClass = new MyClass();
myClass.Name; < -- this will call the parent as well.
Is there anyway to do it?
Thanks in advance
Not really related but since you're not strictly using automatic properties in ClassBase, you should create a private string variable for Name. Something like _name or whatever your internal coding standards dictate.
public class ClassBase
{
private string _name;
public virtual string Name
{
get
{
CallMethod();
return _name;
}
set
{
_name = value;
}
}
}
public class MyClass : ClassBase
{
//Pretty pointless really since you're not doing anything with MyClass.Name.
public new string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
MyClass myClass = new MyClass();
myClass.Name; <-- this will call the parent as well.
Based on "can't change base class" comment there is pretty much nothing you can do to make some code to be executed instead/before/after base class because your property/method will not be called when your new class used as base class (see sample in details part).
Potential solution : if you need to extend specially designed parital class's and it provides extension poinst like CallMethod is marked as partial - it is expected for implemnting portion of the class to implement it :
partial public class ClassBase
{
partial void CallMethod();
public string Name {get {CallMethod(); return "";}}
}
// in generated portion of "ClassBase"
partial public class ClassBase
{
partial void CallMethod() { /* do something here */ }
}
Answer to exact "how to call base class property" is to use base, but hiding property/method this way is confusing (see below):
new public string Name { get { return base.Name;} }
Note that you can't use automatic property in derived class case as you explicitly want some additional code to be executed. If you need set in derived class you need own backing field like:
private string derivedName;
new public string Name {
get { return base.Name + derivedName;}
set { derivedName = value;}
}
Details:
As said in comments hiding base class' properties/methods leads to very confusing behavior. For you case (slightly updated base class with baking field as original sample had infinite recursion):
public class ClassBase
{
private string name;
public string Name
{
get
{
CallMethod();
return name;
}
}
}
You can try to hide Name property in derived class:
public class MyClass : ClassBase
{
// notice "new" to show comiler you know what you doing
// otherwise you'll get warning (but behavior will be the same)
new public string Name { get; set; }
}
The issue with hiding is that base class' method is still easily callable and likely be called by mistake if using derived class as base class:
MyClass myDerved = new MyClass();
ClassBase myDervedAsBase = myDerved;
var name = myDerived.Name; // calls MyClass.Name
var name = myDerivedAsBase.Name; // calls ClassBase.Name
This can be solved by making base class' method/property virtual - but it requires change in base class:
public class ClassBase
{
virtual public string Name { get {... } }
}
public class MyClass : ClassBase
{
override public string Name { get { ... } }
}
If you need to call base class' method/property from derived class usebase.MethodName() like:
override public string Name { get
{
// do some new stuff here
var baseName = base.Name;
// maybe even change result
return baseName;
}
}
If you expect most derived classes to need such behavior it could be better to design base class explicitly to enforce such behavior. For example you can have property to call virtual method before/after computing the value to return like:
public class ClassBase
{
virtual protected string AboutToReturnName(string result)
{
return name;
}
public string Name
{
get
{
var result = "MyName";
return AboutToReturnName(result);
}
}
}
More ideas:
Alternative to virtual is partial methods which works when instead of deriving class is combined from many "partial" parts like ASP.Net pages - see Partial Classes and Methods
If you need notifications around change of property - consider implementing INotifyPropertyChange
if you need to know when properties/method are called in general - consider using interfaces and automatically generate wrapper classes that have pre/post callback. I.e. mocking frameworks (like EasyMoq or RhinoMock) and DI containers (like Unity) provide and use such functionality.
You cannot do it without modifying the code generator. The modification would have to generate a call base.Name.
You can override the property in your subclass with the new operator.
public class MyClass : ClassBase
{
public new string Name { get; set; }
}

Is it possible to implement property setter explicitly while having a getter publicly available?

When I define an interface that contains a write-only property:
public interface IModuleScreenData
{
string Name { set; }
}
and attempt to (naively) implement it explicitly with an intention for the property to also have a publicly available getter:
public class ModuleScreen : IModuleScreenData
{
string IModuleScreenData.Name { get; set; }
}
then I get the following error:
Error 'IModuleScreenData.Name.get' adds an accessor not found in
interface member 'IModuleScreenData.Name'
The error is more or less expected, however, after this alternative syntax:
public class ModuleScreen : IModuleScreenData
{
public string Name { get; IModuleScreenData.set; }
}
has failed to compile, I suppose that what I am trying to do is not really possible. Am I right, or is there some secret sauce syntax after all?
You can do this:
public class ModuleScreen : IModuleScreenData
{
string IModuleScreenData.Name
{
set { Name = value; }
}
public string Name { get; private set; }
}
On a side note, I generally wouldn't recommend set-only properties. A method may work better to express the intention.
You can't change the how the interface is implemented in the inheriting class. That is the whole point.. if you need to do something new with a property you could make a new property that references the inherited properties specific implementation. Interfaces are there so you can conform to a specified standard for object inheritance.
UPDATE:
On second thought.. you should be able to just do this.... this will compile fine:
public class ModuleScreen : IModuleScreenData
{
public string Name { get; set; }
}

Unsure when to use 'base' in C#

I'm trying to teach myself about OOP in C#, but I have a question about when to use base. I understand the general principles, but I'm not sure what's best in the example below. This simple test includes:
An interface with two string properties
An abstract class that implements this interface and adds a couple more string properties
Two classes that implement the abstract class. One uses base and the other doesn't, but they both produce the same output when the program is executed.
My question is: in this example, is one implementation more desirable than the other? I'm not really sure if there are any meaningful differences between TranslationStyleA and TranslationStyleB, or if it's just down to personal preference?
Many thanks for your time and thoughts!
using System;
namespace Test
{
interface ITranslation
{
string English { get; set; }
string French { get; set; }
}
public abstract class Translation : ITranslation
{
public virtual string English { get; set; }
public virtual string French { get; set; }
public string EnglishToFrench { get { return English + " is " + French + " in French"; } }
public string FrenchToEnglish { get { return French + " is " + English + " in English"; } }
public Translation(string e, string f)
{
English = e;
French = f;
}
}
public class TranslationStyleA : Translation
{
public override string English
{
get { return base.English; }
set { base.English = value; }
}
public override string French
{
get { return base.French; }
set { base.French = value; }
}
public TranslationStyleA(string e, string f) : base(e, f)
{
}
}
public class TranslationStyleB : Translation
{
private string english;
public override string English
{
get { return english; }
set { english = value; }
}
private string french;
public override string French
{
get { return french; }
set { french = value; }
}
public TranslationStyleB(string e, string f) : base(e, f)
{
this.English = e;
this.French = f;
}
}
class Program
{
static void Main(string[] args)
{
TranslationStyleA a = new TranslationStyleA("cheese", "fromage");
Console.WriteLine("Test A:");
Console.WriteLine(a.EnglishToFrench);
Console.WriteLine(a.FrenchToEnglish);
TranslationStyleB b = new TranslationStyleB("cheese", "fromage");
Console.WriteLine("Test B:");
Console.WriteLine(b.EnglishToFrench);
Console.WriteLine(b.FrenchToEnglish);
Console.ReadKey();
}
}
}
The first thing that you need to understand is what's going on when you have an automatic property:
public virtual string English { get; set; }
Behind the scenes, the compiler is generating a private field, and getting/setting that private field when you access the property. It is equivalent to this
private string _english;
public virtual string English { get { return _english; } set { _english = value; } }
except that you don't know the name of the private field, and so you cannot access it.
So in your TranslationStyleA class, you are not actually doing anything with the English property, because it just accesses the base class's property directly and doesn't change it's behavior.
// None of this is even needed- we are just delegating to the base class
public override string English
{
get { return base.English; }
set { base.English = value; }
}
Now in the TranslationStyleB class, you are actually changing the behavior of the property (albeit in a fairly useless way). Instead of storing the value for the English property in the base class's auto-implemented private variable, you are storing it in the private variable defined at the derived class level:
private string english;
public override string English
{
get { return english; }
set { english = value; }
}
Neither of these implementations does anything of course, and as implemented neither is needed, since the base class implements the properties perfectly fine itself. So my answer to your original question is that neither is preferred, given the code as you describe it.
Now, let's look at an example where your question is relevant. You only need to override them if you want to change their behavior, for instance.
// We don't want any leading or trailing whitespace, so we remove it here.
public override string English
{
get { return base.English; }
set { base.English = value.Trim(); }
}
We want to delegate to the base class here, because of why these were properties in the first place. Semantically, a property is the same as a field:
public String Foo;
public String Foo { get; set; } // <-- why bother with all this extra { get; set; } stuff?
The reason is that from the compiler's perspective, it is a breaking change in an interface to go from a property to a field. So if I change
public String Foo;
to
public String Foo { get; set; }
Then any code that depends on my code needs to be recompiled. However, if I change
public String Foo { get; set; }
to
private string _foo;
public String Foo { get { return _foo; } set { _foo = value.Trim(); } }
then dependent code still only sees the public property, and does not need recompilation (because the interface of my class has not changed).
If the base class here (Translation) were to change it's behavior for the property English thus:
private string _english;
public String English { get { return _english; } set { _english = value.ToUpper(); } }
the you would want to pick that up in your derived classes!
So considering that properties have behavior associated with them, you should always delegate to the parent class implementation unless that implementation has undesirable effects in your deriving class.
The first style is definitely preferable unless you have some good reason to pick the other one.
The automatically-implemented properties of Translation each add a field, and style B adds more rather than using the ones the compiler added. Style A reuses the one the compiler added, saving some storage.
Additionally, there's no need to override the superclass's properties if you're not going to change their functionality. You could even write another style like this:
public class TranslationStyleC : Translation {
public TranslationStyleC(string e, string f) : base(e, f) {
}
}
You don't really need to override any of the superclass properties to achieve the effect that you intend, since you don't enhance the superclass behavior in any way.
If you remove the abstract modifier from the base Translation, you don't need the subclasses anymore, since it will be functionally equivalent to both.
Now, as to when to use base; you should use it when you want to access functionality in the superclass that's been overridden in the subclass. base calls are always statically bound to the superclass method at compile time; even if the superclass method is virtual (as in your case). For a curious thing that can happen with base calls take a look here.
As mentioned before, style A reuses the fields already declared whereas style B declares new fields. Regarding your question about when to use base, the rule of thumb would be "whenever you would like to reuse logic/code defined in the parent class".
It does come down to how you intend to leverage your constructs.
As implemented, the overridden members on TranslationStyleA are a bit redundant as the consumer could just as easily access the base members without providing the overrides in the base derivation. In cases such as these I personally won't bother overriding the base members at all if doing so doesn't add any value to design.
The second implementation is common when you truly want to override the setting and accessing of base class members, for instance, if the setting of a base class member is the catalyst for initiating another operation then the overriden member on the derivation would be an appropriate place for that to occur.

c# property override Set method

I have a class like the below, I want to override the set value of "School,Country..etc.." property when some one sets a value , i don't want to change the student class but i need to do it in the base class and use it as a generic method
public class Student : BaseClass
{
public String School { get; set; }
public String Country{ get; set; }
}
ie:
When some one sets
Student.School="Harvard",
I need to store it as
Student.School="Harvard my custom value";
Note:
Basically calling OnPropertyChanged in base class rather than the main class.
If you want to do it with aspects, then try Postsharp
Basically you cannot override a non-virtual property. You can hide it by other property with the same name in the derived class, but this won't give you the desired effect if some other code accesses your object by the reference to the base class.
public class Student : BaseClass
{
private string _school
public string School
{
get { return _school; }
set
{
if(value == "Harvard")
value = "Harvard custom";
_school = value;
}
}
public String Country{ get; set; }
}
is that what you mean?
If the School property is in the BaseClass then you can either use the new keyword, or if you control the BaseClass, then you can add the virtual keyword to the School property there, and override it in the Student class.
This is just not doable by solely modifying BaseClass. Think about it this way: If it were possible to "annotate" automatic properties that easily, then we wouldn't need all those <rant>useless tons of</rant> manual property implementations for data model classes that implement INotifyPropertyChanged (same for DependencyProperties).
You need to provide hooks in your subclasses that your base class can use. Implementing PropertyChanged, which you already mentioned, is one possible solution, another one would be a simple method call:
public class Student : BaseClass
{
private string _school;
public String School
{
get { return _school; }
set {
_school = value;
DoMoreChanges(ref _school); // DoMoreChanges is defined in BaseClass
}
}
public String Country{ get; set; }
}
If you have lots of subclasses that need this, you can either use Visual Studio Code Snippets to create the code or T4 templates.
Since your base class does not have those properties you will not be able to modify them from within the base class using standard OOD patterns or principles.
Now if you move the properties to your base class either as normal properties or virtual properties you can modify what you do in the set block of the properties to do extra work.
However if you cannot move these to the base class, and you cannot modify the Student class, as you seem to imply in you question, then you could encapsulate the student class within a new class like StudentProxy or something and then have it expose similar properties that will then call into the real student class how you want.
For example:
public class StudentProxy
{
private Student _student;
public StudentProxy(Student student)
{
this._student = student;
}
public String School
{
get { return _student.School; }
set
{
_student.School = value + " my custom value";
}
}
public String Country
{
get { return _student.Country; }
set
{
_student.Country = value + " my custom value";
}
}
}

Categories

Resources