Enumerator with hidden options - c#

I'm trying to create an excel document generator project. Currently i'm working on cell styles part.
So i have next structure:
public class Styles : List<Style>, ISerializableClass
{
...some special methods...
}
The thing i want to achieve:
When some Style ( item ) is being added to the Styles i want to automatically add/modify/update the Style id.
In other words i want to override the base list.Add() behavior. How can i achieve this?
Or i just should add this method in my Styles class:
public void Add(Style style)
{
/*
* Some mu logic
*/
base.Add(style);
}
To hide the default List.Add() method?

The best practice is to implement IList<T> yourself instead of inheriting from List<T>. You can then delegate most of the implementation to a List<T> field:
public class Styles : IList<Style>, ISerializableClass
{
private List<Style> _list = new List<Style>();
public void Add(Style style)
{
// Your stuff here
_list.Add(style);
}
// ...
}
See this question for more details about why inheriting from List<T> is not a good idea.
And you should almost always avoid hiding base class methods. Because this is easily defeated with code such as:
var stylesList = new Styles(); // Suppose this hides List<T>.Add
var castedList = (IList<Styles>)stylesList;
castedList.Add(new Style()); // <-- this still calls List<T>.Add
IMHO, the only acceptable use case for method hiding is in situations like IEnumerable<T>.GetEnumerator() hiding IEnumerable.GetEnumerator() where both methods do exactly the same thing anyway.

Related

Is a public readonly List<T> bad design?

I am currently writing an application that builds a connection to some sort of Service, gets Data in the form of a few DataTable objects and then is supposed to show it to the user.
In order to store the Data I get I made a class called DataStorage which has a List<DataTable>. Other classes need to be able to edit this List, for example adding objects that are needed or removing them if the user finds them unnecessary. I also have to be able to clear it, should I need a completely new set of data.
I could give the DataStorage methods for that but since the List<T> already offers these, I see no point in encapsulating it like that. So I made it readonly to ensure nobody tries to assign a new object - or even worse, null - and made the access modifier public.
Is this sort of design acceptable or should I always protect fields from direct access, no matter what?
General speaking you should allways take the most general type to reduce any tight coupling and to provide only those members you actually need access to. Having said this in some situations it might be better to use an ICollection instead which provides access to basic methods such as Add, Remove and Clear.
However making the collection readonly or even better a Get-only property is probably a good idea and nothing can be said against this.
We should be very careful with public which means public - whatever.
Do you let any class behave in such a way?
public class Offender {
...
public void Offend(YourClass value) {
...
// In the middle of my routine I've ruined your class
value.Data.Clear();
value.Data.Add(someStuff);
...
}
}
I suggest restricting full access to Data to trusted classes only:
public class YourClass {
// Approved classes (i.e. from your routine) can write, delete, clear...
internal readonly List<Data> m_Data = new List<Data>();
// All the other can only read
public IReadOnlyList<Data> Data {
get {
return m_Data;
}
}
...
// If you let (in some cases) add, delete, clear to untrusted class
// just add appropriate methods:
public void Add(Data data) {
// Here you can validate the provided data, check conditions, state etc.
}
}
If you want to publish a collection with add/remove capability, it is the best if you override the Collection<T> (or ObservableCollection<T>) class, which is very similar to List<T>, but you can override and thus control the add/remove/replace operations. And yes, you can make it public via a get-only property.
public class MyClass
{
private MyCollection myCollection = new MyCollection();
public IList<MyElement> Collection { get { return myCollection; } }
}
internal class MyCollection: Collection<MyElement>
{
// by overriding InsertItem you can control Add and Insert
protected override InsertItem(int index, MyElement item)
{
if (CheckItem(item))
base.InsertItem(index, item);
throw new ArgumentException("blah");
}
// similarly, you can override RemoveItem to control Remove and RemoveAt,
// and SetItem to control the setting by the indexer (this[])
}

Custom (derived) List<T>

Feel free to load your guns and take aim, but I want to understand why you shouldn't do this.
I have created a custom class designed to replace any instances of List (which I use to update XML objects behind them):
public class ListwAddRemove<T> : List<T> {
public event EventHandler<ListModifyEventArgs> OnAdd;
public event EventHandler<ListModifyEventArgs> OnRemove;
new public void Add(T o) {
base.Add(o);
if (OnAdd != null) {
OnAdd(this, new ListModifyEventArgs(o));
}
}
new public void Remove(T o) {
base.Remove(o);
if (OnRemove != null) {
OnRemove(this, new ListModifyEventArgs(o));
}
}
}
The idea is whenever I add or remove an item from this list my bound events will fire and I can deal with the XML behind automatically.
This works like a charm, so far so good.
But how do I handle a conversion between object.ToList() and my derived version?
A lot of people are saying you should derive from Collection instead... why?
You should derive from Collection<T> because it's designed to allow you to override InsertItem, and RemoveItem to add custom behavior such as what you're doing (also SetItem, to add custom behavior when changing an existing item).
It can therefore be used as an IList<T>, and any insertion/removal will automatically use the customisation.
In your case, anyone who casts to IList<T> or the base class List<T> will bypass your custom Add/Remove functionality.
Collection<T> also provides a constructor to wrap an existing list. You can expose this from your derived class to wrap a list generated by Enumerable<T>.ToList().
UPDATE
Whats the syntax to expose the constructor please?
Very simple:
public class ListwAddRemove<T> : Collection<T>
{
public ListwAddRemove<T>()
{
}
public ListwAddRemove<T>(IList<T> list) : base(list)
{
}
... implementation of overrides for InsertItem, SetItem, RemoveItem ...
}
Then use it as follows:
IList<SomeType> list = ....ToList();
ListwAddRemove<SomeType> myList = new ListwAddRemove<SomeType>(list);
For one,
void DoSomeAddingToList(List<int> list) {
list.Add(1);
}
var list = new ListwAddRemove<int>();
DoSomeAddingToList(list);
will not trigger the events. That might lead to strange effect, especially if you're not the only one using the class.
List<T> defines a very specific behaviour for Add and Remove (since it's a concrete class), and users might rely on exactly this behaviour.
I think this is generally true for using a new modifier, so this language feature should be used with caution, especially on public methods.
As others have mentioned, implementing IList<T> (using delegation/aggregation) is probably the better choice.

How do I ensure a Class can call a method on another Class, but not other Classes can call that method?

I have two classes that I'd like to keep in separate files.
namespace GridSystem
{
public class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
}
namespace GridSystem
{
public class GridItem
{
public void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
}
How do I ensure no other classes are allowed to call InformAddedToGrid?
I'm trying to emulate Actionscript namespaces, which can be used on a method, in place of public, private, internal, etc. It doesn't exactly protect the method, but forces an extra step of including the namespace before the method can be accessed. Is there an alternative approach to this in C#?
If GridItem itself can be hidden from the outside world as well I would consider putting GridItem inside Grid as a nested class. That way it won't be visible outside of the class
http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C
Not that you should do this, you should do what TGH suggests, have a public interface for GridItem, and have gridItem nested in Grid (then have a factory method on Grid to create Items and use partial Grid class to have them in separate files).
Because there isn't a way of having friend methods ( you can do friend classes through InternalsVisibleToAttribute )
You COULD do this ( but don't... )
public partial class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
public class GridItem
{
public void InformAddedToGrid()
{
if (new StackTrace().GetFrame(1).GetMethod().DeclaringType !=
typeof(Grid)) throw new Exception("Tantrum!");
Console.WriteLine("Grid called in...");
}
}
then
var g = new Grid();
g.AddItem(new GridItem()); // works
new GridItem().InformAddedToGrid(); // throws a tantrum...
A really ugly answer would be to make it private and use reflection.
Another ugly answer would be to make it throw an exception if the caller is wrong.
Both of these are much slower to execute than a normal call also.
I don't think there's a good answer. C# doesn't have friends.
IMHO the answer is simple: access modifiers are just there to remind the programmer of the intent of how public/private a class should be. Through reflection you can lift those barriers.
The usage you make of a class is all in your hands: if your class is meant to only be used in one place, make it so. If anything, if a class has a special way of being used, document it - put it in the XML comments.
That said, in this specific example I'd believe since the GridItem doesn't add itself to the grid, it's not its job to notify about it (what if "I've not been added to the grid"?). I think InformAddedToGrid belongs somewhere in your Grid class as a private method, where there's a concept of adding an item... assuming that's what AddItem(GridItem) really does.
You can do it as TGH suggested, with nested classes, except the other way around. Nest Grid within GridItem and make InformAddedToGrid private. Here I use a nested base class so the public API can remain the same. Note that no one outside of your assembly can inherit from GridBase because the constructor is internal.
public class GridItem
{
public class GridBase
{
internal GridBase() { }
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
private void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
public class Grid : GridItem.GridBase { }
Another option is to have GridItem explicitly implement an internal interface. This way no one outside of your assembly can use the interface by name and therefore cannot call InformAddedToGrid.
public class Grid
{
public void AddItem(GridItem item)
{
((IGridInformer)item).InformAddedToGrid();
}
}
public class GridItem : IGridInformer
{
void IGridInformer.InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
internal interface IGridInformer
{
void InformAddedToGrid();
}

What's the best practice for alternate solution of Multi-Inheritance in C#

I have some classes inherit from existing Windows Controls like TextBox and DateTimePicker, ..etc
I want to add custom functionalities for these classes like (Read, Alert, ...etc)
these added functionalities are the same in all these classes
The problem is: these classes inherited from difference parents so I can't put my added functionalities in the parent class,
What's the best practice in this case:
repeat the code in each inherited
class
Use a separated class have the
functionalities as Static Methods
with parameter from an interface, implement this interface for the classes and
then pass them.
Use a separated class like the second approach but with Dynamic parameter (which added in C# 4.0)
or other !!
Thanks in advance
I'd consider option 4: composition.
First, define your set of functionality. We'll assume that your partial list is exclusive, so "Read" and "Alert."
Second, create a single class that implements this functionality, something like MyCommonControlBehaviors. I'd prefer this implementation not be static if possible, though, it may be generic.
public MyCommonControlBehaviors
{
public Whatever Read() { /* ... */ }
public void Alert() {}
}
Third, use composition to add an instance of this class to each of your custom control types and expose that functionality through your custom control:
public class MyCustomControl
{
private MyCommonControlBehaviors common; // Composition
public Whatever Read() { return this.common.Read(); }
public void Alert() { this.common.Alert(); }
}
Depending on specifics, you can get creative to the degree necessary. E.g., perhaps your custom behaviors need to interact with private control data. In that case, make your control implement a common ICommonBehaviorHost interface that your common behaviors need. Then pass the control into the behavior class on construction as an instance of ICommonBehaviorHost:
public interface ICommonBehaviorHost
{
void Notify();
}
public class MyCommonControlBehaviors
{
ICommonBehaviorHost hst = null;
public MyCommonControlBehaviors(ICommonBehaviorHost host)
{
this.hst = host;
}
public void Alert() { this.hst.Notify(); } // Calls back into the hosting control
// ...
}
public class MyCustomControl : ICommonBehaviorHost
{
private MyCommonControlBehaviors common = null;
public MyCustomControl() { common = new MyCommonControlBehaviors(this); }
public Whatever Read() { return this.common.Read(); }
public void Alert() { this.common.Alert(); }
void ICommonBehaviorHost.Notify() { /* called by this.common */ }
}
Use Composition instead of Inheritence!
If you must, what I would probably do is create extension methods for each class and then reference the actual coded needed for these in some other object all the extension methods can call.
This way the code isn't duplicated, and the extension methods make it look like the methods should be in the object.
It's the same essentially by creating a static method and doing: Functions.DoSomething(my_Object);
But I always like: my_Object.DoSomething() better in an OO language.
I would suggest defining an interface for the behaviors, and then (to keep from repeating yourself) create extension methods on that interface definition for your shared methods. (Kinda like your second option, only with extension methods instead of totally static methods).

How to call a shared member on types with different types?

I have different sets of custom Winforms controls all deriving from Control such as:
CalculatorPanel, GraphPanel, DisplayPanel, etc : Control
I use a single Form to display one or more of these sets depending on what the user wants to see.
All of them has a member called:
Input
where the type is different such as:
CalculatorInput, GraphInput, DisplayInput, etc.
How do I store them in a list or some other collection where I can call the Input property without any problem?
Should I use a common interface for each? Then it has to be generic. How will I specify the type?
Right now I use something like this to add/remove controls:
Panels = Dictionary <Enum, Control> ...
Panels.Add (PanelType.Calculator, new CalculatorInput ().Controls);
...
so later I can say:
Form.Add/RemoveControls (Panels[PanelType.Calculator])
but how would I set their Input property when I need to at runtime. So if the user switches to the GraphPanel, I want to be able to set it's Input right after I added its controls to the Form.
Is there a design pattern or a technique to solve this?
EDIT: Properties of each input type (no methods) are as follows:
CalculatorInput:
.Result
.LastOperation
...
GraphInput:
.Result
.SelectedNode
...
DisplayInput:
.Result
.CurrentColor
...
Basically these inputs are just types to be bound to the appropriate UI. So if the UI has some properties, they are bound to these input, which is why when I assign a new input, the UI will update automatically.
EDIT2:
So all these inputs are separate no inheritance, etc.
But are defined in appropriate rollouts as follows:
class CalculatorPanel
{
CalculatorInput Input
}
class GraphPanel
{
GraphInput Input
}
class DisplayPanel
{
DisplayInput Input
}
I think what you need is an INTERFACE for your Input that all classes will inherit from..
public interface MyInputInterface
{
void YourInputFunction();
}
public class CalculatorPanel : Control, MyInputInterface
{
..
..
void MyInputInterface.YourInputFunction()
{
// do your code specific to calculator panel here
}
}
public class GraphPanel : Control, MyInputInterface
{
..
..
void MyInputInterface.YourInputFunction()
{
// do your code specific to graph panel here
}
}
Then, you can build a list of anything that implements MyInputInterface
public List<MyInputInterface> MyInputList = new List<MyInputInterface>();
and work with that list as needed... The Interface is a contract of any object utilizing it to guarantee it has the associated properties, fields, functions, etc.
Since the inputs are essentially separate, they could implement an interface for the small amount of common functionality, but it probably wouldn't accomplish much (it would help to know the data types of the input class members). To get access to the non-common functionality (which is most of the input objects), you'll still need extra logic to get things working:
if (currentControl is CalculatorPanel)
{
CalculatorInput input = (currentControl as CalculatorPanel).Input;
// ...
}
else if (currentControl is GraphPanel)
{
}
etc.

Categories