Usage of the sealed string property in c# - c#

I was writing a class in c#.
I stumbled upon the this piece of suggestion offered by a code refactor. And i didnt
get what exactly the tool meant when it offered this suggestion/improvement.
Situation :
I was using this.Text property to set the title in the constructor of my Form class.
Form()
{
//some initialization code ...
//...
this.Text = "Non modal form"; //Suggestion offered here..
}
The code refactor tool prompted a warning : saying accessing virtual member
To correct this the tool automatically added a property
public override sealed string Text
{
get { return base.Text; }
set { base.Text = value; }
}
Can anyone explain me how, adding a sealed property will affect/improve the situation.
Cheers

You are calling a virtual member in a constructor. There is no gaurentee that YOUR code will run if the class is inherited and that property is called. Making it sealed prevents this as it can not be overridden in child classes. This shouldn't affect anything in this specific example.

It will help since no derived classes can override it.

As you are dealing with a Form, another option would be to just move your initialization code to the Load event handler (as described by Jon Skeet here):
Load += delegate
{
this.Text = "Non modal form";
};
Using the Load event is much simpler than creating sealed properties, especially if you are accessing more than one virtual property.

Since you are setting a virtual property in your constructor, refactoring tool is suggesting to seal the property so that the value cannot be changed in the inherited classes it cannot be overriden in the inherited classes.
This does not improve performance, nor it makes sense in the scenario you have (a Form). So I would just ignore it.

Related

Mask inherited public property [duplicate]

Is this the way to hide properties in derived controls?
public class NewButton : Button
...
[Browsable ( false )]
public new ContentAlignment TextAlign { get; set; }
Also this hides the property in the Properties window in the designer but how can I also hide the property in code?
From code, the closest you can do it to hide it, and perhaps make it a pain to call directly - note that even when hidden it is callable, and none of this will work past a cast:
// about the closest you can do, but not really an answer
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("just cast me to avoid all this hiding...", true)]
public new ContentAlignment TextAlign { get; set; }
Personally, I wouldn't bother. It isn't robust (just cast).
You can use the [EditorBrowsable] attribute, as documented here.
[EditorBrowsable(EditorBrowsableState.Never)]
public bool HideMeInIntellisense
{
// ...
From the documentation:
...the IntelliSense engine in Visual Studio uses this attribute to determine whether to show a property or method.
However, users can override this in VS settings. ReSharper also has a setting that controls whether this attribute is honoured in its IntelliSense.
Out of curiousity, why do you want to hide something from users? Just because a member is hidden in the way described above doesn't mean you couldn't use it in code and compile it successfully. It just inhibits the discoverability of the member.
No, you can remove them from the designer (as shown) but you cannot really hide them form code as that would violate the substitution principle. It has been asked & answered many times here, see for example this SO question.
Maybe what you want to do is derive from ContainerControl or UserControl, add a Button to that control and just expose those parts of the Button interface you want to keep.
Why don't you make it private? It guarantees that ancestors will not see it.
Edit:
In this case you have to inherit a new class from the base and use your new class, which now hides ths property.
public class MyTextBox: TextBox
{
...
private new ContentAlignment TextAlign
{
get { return base.ContentAlignment; }
set { base.ContentAlignment = value; }
}
}

C# User Control Dependency Injection [duplicate]

Call me crazy, but I'm the type of guy that likes constructors with parameters (if needed), as opposed to a constructor with no parameters followed by setting properties. My thought process: if the properties are required to actually construct the object, they should go in the constructor. I get two advantages:
I know that when an object is constructed (without error/exception), my object is good.
It helps avoid forgetting to set a certain property.
This mindset is starting to hurt me in regards to form/usercontrol development. Imagine this UserControl:
public partial class MyUserControl : UserControl
{
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
At designtime, if I drop this UserControl on a form, I get an Exception:
Failed to create component 'MyUserControl' ...
System.MissingMethodException - No parameterless constructor defined for this object.
It seems like, to me, the only way around that was to add the default constructor (unless someone else knows a way).
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
The whole point of not including the parameterless constructor was to avoid using it. And I can't even use the DesignMode property to do something like:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
if (this.DesignMode)
{
InitializeComponent();
return;
}
throw new Exception("Use constructor with parameters");
}
}
This doesn't work either:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
Fine, moving along ...
I have my parameterless constructor, I can drop it on the form, and the form's InitializeComponent will look like this:
private void InitializeComponent()
{
this.myControl1 = new MyControl();
// blah, blah
}
And trust me, because I did it (yes, ignoring the comments Visual Studio generated), I tried messing around and I passed parameters to InitializeComponent so that I could pass them to the constructor of MyControl.
Which leads me to this:
public MyForm()
{
InitializeComponent(); // Constructed once with no parameters
// Constructed a second time, what I really want
this.myControl1 = new MyControl(anInt, aString);
}
For me to use a UserControl with parameters to the constructor, I have to add a second constructor that I don't need? And instantiate the control twice?
I feel like I must be doing something wrong. Thoughts? Opinions? Assurance (hopefully)?
Design decisions made regarding the way Windows Forms works more or less preclude parameterized .ctors for windows forms components. You can use them, but when you do you're stepping outside the generally approved mechanisms. Rather, Windows Forms prefers initialization of values via properties. This is a valid design technique, if not widely used.
This has some benefits, though.
Ease of use for clients. Client code doesn't need to track down a bunch of data, it can immediately create something and just see it with sensible (if uninteresting) results.
Ease of use for the designer. Designer code is clearer and easier to parse in general.
Discourages unusual data dependencies within a single component. (Though even microsoft blew this one with the SplitContainer)
There's a lot of support in forms for working properly with the designer in this technique also. Things like DefaultValueAttribute, DesignerSerializationVisibilityAttribute, and BrowsableAttribute give you the opportunity to provide a rich client experience with minimal effort.
(This isn't the only compromise that was made for client experience in windows forms. Abstract base class components can get hairy too.)
I'd suggest sticking with a parameterless constructor and working within the windows forms design principles. If there are real preconditions that your UserControl must enforce, encapsulate them in another class and then assign an instance of that class to your control via a property. This will give a bit better separation of concern as well.
There are two competing paradigms for designing classes:
Use parameterless constructors and set a bunch of properties afterwards
Use parameterized constructors to set properties in the constructor
The Visual Studio Windows Forms Designer forces you to provide a parameterless constuctor on controls in order to work properly. Actually, it only requires a parameterless constructor in order to instantiate controls, but not to design them (the designer will actually parse the InitializeComponent method while designing a control). This means that you can use the designer to design a form or user control without a parameterless constructor, but you cannot design another control to use that control because the designer will fail to instantiate it.
If you don't intend to programmatically instantiate your controls (i.e. build your UI "by hand"), then don't worry about creating parameterized constructors, since they won't be used. Even if you are going to programmatically instantiate your controls, you may want to provide a parameterless constructor so they can still be used in the designer if need be.
Regardless of which paradigm you use, it is also generally a good idea to put lengthy initialization code in the OnLoad() method, especially since the DesignMode property will work at load time, but not work in the constructor.
I would recommend
public partial class MyUserControl : UserControl
{
private int _parm1;
private string _parm2;
private MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2) : this()
{
_parm1 = parm1;
_parm2 = parm2;
}
}
As this way the base constructor is always called first and any references to components are valid.
You could then overload the public ctor if need be, ensuring the control is always instantiated with the correct values.
Either way, you ensure that the parameterless ctor is never called.
I haven't tested this so if it falls over I apologise!
This is unfortunately a design issue that will occur frequently, not just in the control space.
There are often situations where you need to have a parameterless constructor, even though a parameterless constructor is not ideal. For example, many value types, IMO, would be better off without parameterless constructors, but it's impossible to create one that works that way.
In these situations, you have to just design the control/component in the best manner possible. Using reasonable (and preferably the most common) default parameters can help dramatically, since you can at least (hopefully) initialize the component with a good value.
Also, try to design the component in a way that you can change these properties after the component is generated. With Windows Forms components, this is typically fine, since you can pretty much do anything until load time safely.
Again, I agree - this isn't ideal, but it's just something we have to live with and work around.
Well, in short, the designer is the kind of guy that likes parameter-less constructors. So, to the best of my knowledge, if you really want to use parameter based constructors you are probably stuck with working around it one way or the other.
Just do this:
public partial class MyUserControl : UserControl
{
public MyUserControl() : this(-1, string.Empty)
{
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
if (parm1 == -1) { ... }
InitializeComponent();
}
}
Then the 'real' constructor can act accordingly.
Provide a parameterless constructor for the designer and make it private - if you really must do it this way... :-)
EDIT: Well of course this won't work for UserControls. I obviously wasn't thinking clearly. The designer need to execute the code in InitializeComponent() and it's can't work if the constructor is private. Sorry about that. It does work for forms, however.
It's quite a while since the question was asked, but maybe my approach is helpful to somebody.
I personally also prefer to use parameterized Constructors to avoid forgetting to set a certain property.
So instead of using the actual Constructor I simply define a public void PostConstructor where all things are put you would normally put in the Constructor. So the Actual Constructor of the UserControl always contains only InitializeComponent().
This way you don't have to adjust your favourite programming paradigm to VisualStudios needs to run the Designer properly. For this programming schema to work it has to be followed from the very bottom.
In practice this PostConstructionalizm would look somewhat like this:
Let's start with a Control at the bottom of your UserControl call hierarchy.
public partial class ChildControl : UserControl
{
public ChildControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
//setting parameters/fillingdata into form
}
}
So a UserControl containing the ChildControl would look something like that:
public partial class FatherControl : UserControl
{
public FatherControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
ChildControl.PostConstructor(YourParameters[])
//setting parameters/fillingdata into form
}
}
And finally a Form calling one of the User Control simply puts the PostConstructor after InitializeComponent.
public partial class UI : Form
{
public UI(yourParameters[])
{
InitializeComponent();
FatherControl.PostConstructor(yourParameters[]);
}
}
I have a way to work around it.
Create a control A on the form with the parameterless constructor.
Create a control B with parameterized constructor in the form contstructor.
Copy position and size from A to B.
Make A invisible.
Add B to A's parent.
Hope this will help. I just encountered the same question and tried and tested this method.
Code for demonstrate:
public Form1()
{
InitializeComponent();
var holder = PositionHolderAlgorithmComboBox;
holder.Visible = false;
fixedKAlgorithmComboBox = new MiCluster.UI.Controls.AlgorithmComboBox(c => c.CanFixK);
fixedKAlgorithmComboBox.Name = "fixedKAlgorithmComboBox";
fixedKAlgorithmComboBox.Location = holder.Location;
fixedKAlgorithmComboBox.Size = new System.Drawing.Size(holder.Width, holder.Height);
holder.Parent.Controls.Add(fixedKAlgorithmComboBox);
}
holder is Control A, fixedKAlgorithmComboBox is Control B.
An even better and complete solution would be to use reflect to copy the properties one by one from A to B. For the time being, I am busy and I am not doing this. Maybe in the future I will come back with the code. But it is not that hard and I believe you can do it yourself.
I had a similar problem trying to pass an object created in the main Windows Form to a custom UserControl form. What worked for me was adding a property with a default value to the UserControl.Designer.cs and updating it after the InitializeComponent() call in the main form. Having a default value prevents WinForms designer from throwing an "Object reference not set to an instance of an object" error.
Example:
// MainForm.cs
public partial class MainForm : Form
public MainForm()
{
/* code for parsing configuration parameters which producs in <myObj> myConfig */
InitializeComponent();
myUserControl1.config = myConfig; // set the config property to myConfig object
}
//myUserControl.Designer.cs
partial class myUserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
// define the public property to hold the config and give it a default value
private myObj _config = new myObj(param1, param2, ...);
public myObj config
{
get
{
return _config ;
}
set
{
_config = value;
}
}
#region Component Designer generated code
...
}
Hope this helps!

Hiding unwanted properties in custom controls

Is this the way to hide properties in derived controls?
public class NewButton : Button
...
[Browsable ( false )]
public new ContentAlignment TextAlign { get; set; }
Also this hides the property in the Properties window in the designer but how can I also hide the property in code?
From code, the closest you can do it to hide it, and perhaps make it a pain to call directly - note that even when hidden it is callable, and none of this will work past a cast:
// about the closest you can do, but not really an answer
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("just cast me to avoid all this hiding...", true)]
public new ContentAlignment TextAlign { get; set; }
Personally, I wouldn't bother. It isn't robust (just cast).
You can use the [EditorBrowsable] attribute, as documented here.
[EditorBrowsable(EditorBrowsableState.Never)]
public bool HideMeInIntellisense
{
// ...
From the documentation:
...the IntelliSense engine in Visual Studio uses this attribute to determine whether to show a property or method.
However, users can override this in VS settings. ReSharper also has a setting that controls whether this attribute is honoured in its IntelliSense.
Out of curiousity, why do you want to hide something from users? Just because a member is hidden in the way described above doesn't mean you couldn't use it in code and compile it successfully. It just inhibits the discoverability of the member.
No, you can remove them from the designer (as shown) but you cannot really hide them form code as that would violate the substitution principle. It has been asked & answered many times here, see for example this SO question.
Maybe what you want to do is derive from ContainerControl or UserControl, add a Button to that control and just expose those parts of the Button interface you want to keep.
Why don't you make it private? It guarantees that ancestors will not see it.
Edit:
In this case you have to inherit a new class from the base and use your new class, which now hides ths property.
public class MyTextBox: TextBox
{
...
private new ContentAlignment TextAlign
{
get { return base.ContentAlignment; }
set { base.ContentAlignment = value; }
}
}

UserControl as an interface, but visible in the Designer

So we have a C# WinForms project with a Form that contains a bazillion UserControls. Each UserControl naturally exposes all the UserControl methods, properties, etc. in addition to its own specific members.
I've been thinking that one way to reduce the complexity of dealing with these UserControls is to access them through an interface. So instead of drag-and-drop to put the UserControl on the form, something like this in the constructor:
public class MyGiantForm
{
ICustomerName cName;
public MyForm()
{
InitializeComponent();
var uc = new SomeCustomerNameUserControl();
this.Controls.Add(uc);
cName = uc;
}
}
SomeCustomerNameUserControl implements ICustomerName, naturally, and ICustomerName contains the specific properties I really care about (say, FirstName and LastName). In this way I can refer to the UserControl through the cName member and, instead of being bowled over by all the UserControl members, I get only those in ICustomerName.
All well and good, but the problem is that if I do it this way, I can't see SomeCustomerNameUserControl in the Designer. Does anybody know I way I can do this but still see the UserControl on the form's design surface?
EDIT: One way to do this, which isn't overly complicated, is to put the controls on a base form. By default (in C#) the control members are private. Then I create a property for each control exposing it through the interface.
However, I'd be interested in some other way to do this, even if it's more complex. There seems to be some way to do it with IDesignerHost, but I can't find any applicable examples.
If SomeCustomerNameUserControl is defined like this:
class SomeCustomerNameUserControl : UserControl, ICustomerName
{
}
You can still drop this control in the designer (which creates someCustomerNameUserControl1) and do this whenever you need to:
ICustomerName cName = someCustomerNameUserControl1;
Maybe I'm missing something, but I think it's that simple.
There's a way to accomplish what you want -- hiding the members you don't want to see -- but make it apply automatically, without requiring others' cooperation in terms of them using a custom interface. You can do it by reintroducing all the members you don't want to see, and tagging them with attributes.
This is what Windows Forms does when, for example, a base-class property doesn't mean anything for a particular descendant. For example, Control has a Text property, but a Text property is meaningless on, say, a TabControl. So TabControl overrides the Text property, and adds attributes to its override saying "By the way, don't show my Text property in the Property Grid or in Intellisense." The property still exists, but since you never see it, it doesn't get in your way.
If you add an [EditorBrowsable(EditorBrowsableState.Never)] attribute to a member (property or method), then Intellisense will no longer show that member in its code-completion lists. If I'm understanding your question correctly, this is the big thing you're trying to achieve: make it hard for application code to use the member by accident.
For properties, you probably also want to add [Browsable(false)] to hide the property from the Property Grid, and [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] to prevent the designer from writing the property's value to the .designer.cs file.
These will make it very difficult to accidentally use the method/property. They're still not a guarantee, though. If you do need a guarantee, then throw in an [Obsolete] attribute too, and build with "Treat warnings as errors" -- then you're taken care of.
If the base member is virtual, you probably want to override it, and have your override simply call base. Don't throw an exception, since the overridden member will probably be called by the base class during the normal course of events. On the other hand, if the base member isn't virtual, then you want to use "new" instead of "override", and you can decide whether your implementation should call base, or just throw an exception -- nobody should be using your reintroduced member anyway, so it shouldn't matter.
public class Widget : UserControl
{
// The Text property is virtual in the base Control class.
// Override and call base.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The Text property does not apply to the Widget class.")]
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
// The CanFocus property is non-virtual in the base Control class.
// Reintroduce with new, and throw if anyone dares to call it.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The CanFocus property does not apply to the Widget class.")]
public new bool CanFocus
{
get { throw new NotSupportedException(); }
}
// The Hide method is non-virtual in the base Control class.
// Note that Browsable and DesignerSerializationVisibility are
// not needed for methods, only properties.
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The Hide method does not apply to the Widget class.")]
public new void Hide()
{
throw new NotSupportedException();
}
}
Yes, this is a fair bit of work, but you only have to do it once... per member, per class... umm, yeah. But if those base-class members really don't apply to your class, and having them there will cause confusion, then it may be worth going to the effort.
'I want ICustomerName to be the only option for accessing the UserControl's variable. The idea is that a developer doesn't have to "just remember" to cast it.'
The problem you are having is that you have two completely divergent uses for your form and the controls it hosts. There is no trick built into Visual Studio or winforms which solves this neatly for you. It may be possible, but there is a much cleaner and object oriented way to separate the two methods of interacting with the controls.
If you want to hide the fact that these objects inherit from UserControl, and just want to treat them as IDoSomeThingYouShouldDealWith, you need to separate the logic that deals with the presentation concerns (designer + UI logic) from your business logic.
Your form class, should rightly deal with the controls as UserControls, docking, anchoring etc etc, nothing special here. You should put all the logic that needs to deal with ICustomerName.FirstName = etc into a completely separate class. This class doesn't care or know about fonts and layout, it just knows that there is another instance that can present a customer name; or a DateTime as a 'date of birth choosing' control properly etc.
This is a really lame example, but I have to go right now. You should be able to get the idea covered here in more detail:
public interface ICustomerName
{
void ShowName(string theName);
}
public partial class Form1 : Form, ICustomerName
{
public Form1()
{
InitializeComponent();
}
#region ICustomerName Members
public void ShowName(string theName)
{
//Gets all controls that show customer names and sets the Text propert
//totheName
}
#endregion
}
//developers program logic into this class
public class Form1Controller
{
public Form1Controller(ICustomerName theForm) //only sees ICustomerName methods
{
//Look, i can't even see the Form object from here
theForm.ShowName("Amazing Name");
}
}
After you add the UserControl using the designer, you can set GenerateMember to false in the Properties window to suppress generation of a member.
You could then use some other technique in the constructor to assign your cName reference, e.g.:
foreach(Control control in this.Controls)
{
cName = control as ICustomerName;
if (cName != null) break;
}
cName would then be the only reference to the UserControl.
You could write an extension method that would allow you to return any controls on the form that implement an interface.
public static class FormExtensions
{
public static IDictionary<string, T> GetControlsOf<T>(this Form form)
where T: class
{
var result = new Dictionary<string, T>();
foreach (var control in form.Controls)
{
if ((control as T) != null)
result.Add((control as T).Tag, control as T);
}
return result;
}
}
Then in your form you could call it whereever you want by:
this.GetControlsOf<ICustomerName>()["NameOfControlHere"];
In the event that it returns more than one user control you would need to handle that some how, perhaps by adding Tag property to the interface to uniquely keep track of each user control or something, like so
public partial class UserControl1 : UserControl, ICustomerName
{
public string Tag { get { return this.Name; } }
}
You can then drag and drop the user controls onto your form from the designer. Tag will always return the name of your control, which will allow you to directly access the control through the IDictionary's interface. You're developers could put whatever unique identifier they want in the name of the control, and it would carry through to the interface.
Also, it should be noted that this approach will ALSO allow you to use this on ALL forms in your solution.
The only other thing you would need to do is set your GenerateMember to false.
you could as well do as Bob said but assign all your member variables in the constructor, then you have it in one place.
It almost seems like you want to implement a mediator pattern. Instead of having to deal with each of the bazillion UserControls directly, you'd interact with them through the mediator. Each mediator would define the slim interface you want to see from each control. This would reduce the overall complexity by making your design more explicit and concise. For example, you wouldn't need the 20 properties and 50 methods available on one of your controls. Instead you'd deal with the mediator for that control which defines the 2 properties and 5 methods you really care about. Everything would still show up in the designer, but other parts of your app would not be interacting with those controls -- they'd interact with the mediators.
One of the big advantages to this approach is it greatly simplifies your maintenance. If you decide the MyCrappyUserControl needs to be rewritten because the implementation is bad, you just need to update the mediator class for that control. All the other classes that interact with the control do so through the mediator and would be unchanged.
Ultimately it comes down to discipline: you and your team need to be disciplined enough to use the mediators/interfaces/whatever instead of the directly hitting the controls. Institute an over the shoulder code review by a leader programmer if your team is on the low end of the discipline scale.
Assume that MyUserControl is defined like this:
class MyUserControl : UserControl, IMyInterface
{
// ...
}
Then in your form, you should have something like this:
public class MyForm : Form
{
IMyInterface cName;
public MyForm()
{
InitializeComponent();
cName = new MyUserControl();
Controls.Add((UserControl)cName);
}
}
This way, cName is the only way to access this instance of our usercontrol.

How do I hide a method so it's not called by programmers but still usable in code?

I have a class called Ship and a class called Lifeboat
Lifeboat inherits from Ship.
Ship contains a method called Validate() which is called before save and it has an abstract method called FurtherValidate() which it calls from Validate. The reason this is in place is so when you call validate on the base it also validates the class that is inheriting. So we have
public class Ship
public bool Validate()
{
//validate properties only found on a ship
FurtherValidate();
}
public abstract bool FurtherValidate();
So Lifeboat has
public override bool FurtherValidate()
{
//validate properties only found on a lifeboat
}
This means anyone implementing Ship also needs to provide their own validation for their class and it's guaranteed to be called on the save as the base ship. Validate() is called which in turns calls the inherited validate.
How can we re work this so we still force inherited classes to implement FurtherValidate() but FurtherValidate() can never be called by the programmer. Currently you can called Lifeboat.FurtherValidate() and I want to somehow prevent this.
Short answer is, you can't hide the derived method from the class that's deriving it. However, you can refactor your code to accomplish what you're trying to achieve:
public class Ship
{
public virtual bool Validate()
{
//validate properties only found on a ship
return true;
}
}
public class Lifeboat : Ship
{
public override bool Validate()
{
base.Validate();
// lifeboat specific code
return true;
}
}
protected abstract bool FurtherValidate();
only Ship and Lifeboat can see it now.
EDIT:
Lifeboat must be able to see it. How should it be able to override FurtherValidate when it can't even see it. I would rename it to ValidateCore, the 'Core' part (to me) implies that it should not be called without a very good reason.
I don't think it's easy to make it abstract but not visible. You need to have some faith in your lifeboat ;)
The exact scenario you describe isn't possible. You can restrict access to the FurtherValidate method to only derived classes by using the protected access modifier. You could also restrict it to only classes in the same assembly by using the internal modifier, but this would still allow the programmer writing the derived class to call FurtherValidate any time they wish. Using both protected and internal combines the two and really means that is restricted to derived classes or classes defined in the same assembly.
Using the [EditorBrowsable] attribute is an IDE trick that will hide the method from IntelliSense (unless the other programmer has turned on the right options in VS). That will effectively prevent most people from calling it (if they can't see it, it doesn't exist).
You could possibly achieve this using reflection to interrogate who your caller is, but I think the performance costs of doing this would be too high compared to the benefit.
The most simple answer would be to make the method protected. This allows the inheritors to call it but does not make it publicly available. However there is nothing to stop the inheriting classes changing the method to public.
I would be more inclined to remove the FurtherValidate method entirely and have any inheriting classes override Validate, calling base.Validate() if they wish. This allows any class that inherits from ship to have a greater degree of control over the validate method.
protected is the correct approach here. But in another situation, you may wish to use editorbrowsableattribute which will hide the method from intellisense. You can still call it, but it slows down devs from calling something that could blow up the program, and will usually force them to read your giant comment-warnings.
Making it protected instead of public will at least prevent outside objects from calling it.
I see a code smell here, since Validate isn't part of the functional responsibility of a ship. In other words, I think maybe you're trying to solve a problem using inheritance when maybe that's not the best solution. Try refactoring your validation logic so that you inject your validation in to the class. This will make better sense in terms of a domain object Ship, since ships don't validate themselves, they're validated externally. If you want to enforce that there must be a validator, then you can throw an exception if the property is null.
protected IValidator FurtherValidation { private get; set; }
public bool Validate()
{
//validate properties only found on a ship
if (FurtherValidation == null)
throw new ValidationIsRequiredException();
if (!FurtherValidation.IsValid(this))
// logic for invalid state
}
You could mark the method as protected so only inheriting classes can access it. This does not prevent inheritors from exposing the method through another public method but that's usually not a major concern.
Probably you could try the private modifier

Categories

Resources