I have a set of interfaces using each others like this:
public interface IModel
{
string Name { get; }
IModelParameters Parameters { get; }
}
public interface IModelParameter
{
int Value { get; }
}
public interface IModelParameters: IList<IModelParameter>
{
void DoSomething();
}
And to implement those interfaces, I have defined those classes:
public class Model: IModel
{
string Name { get; internal set; }
public ModelParameters Parameters { get; private set; }
IModelParameters IModel.Parameters { get { return Factors; } }
}
public class ModelParameter: IModelParameter
{
int Value { get; internal set; }
}
public class ModelParameters: List<ModelParameter>, IModelParameters
{
void DoSomething()
{
// actual code
}
}
This does not compile because List<ModelParameter> implements IList<ModelParameter> and not IList<IModelParameter> as required by IModelParameters
Changing ModelParameters to be List<IModelParameter> fixes the compilation but it breaks Entity Framework migration generation because it no longer recognizes the list as a navigation property because the type parameter is an interface, not a regular class.
I could also have ModelParameters not implement IModelParameters and declare a second class that gets instantiated and filled directly in the IModelParameters.Factors getter inside Model
But this feels inefficient as it effectively creates two instances of the same list, one for Entity framework and a temporary one for use by the rest of the application. And because this temporary is filled at runtime, it introduces another potential point of failure.
This is why I'm trying to find a way to express the fact List<ModelParameter> implements IList<IModelParameter> just fine because ModelParameter implements IModelParameter itself.
I have a feeling that covariance/contravariance might be of help here, but I'm not sure how to use that.
You cannot do this. It it was possible to cast a List<ModelParameter> to IList<IModelParameter> you could try adding a object of another type to the list, i.e. class MyOtherModelParam : IModelParameter. And that is a contradiction since the type system guarantees that the list only contains ModelParameter objects.
You could replace it with IReadOnlyList<T>, since this interface do not expose any add or set methods it is safe to cast a List<ModelParameter> to IReadOnlyList<IModelParameter>.
Another possible solution would be to just remove the interface. If you intend to have only one implementation of IModelParameter, the interface serves little purpose, and you might as well just remove it.
I started writing this as a real question, but I kept thinking of answers along the way, thought I would post it anyway to see if there were any other solutions
I can think of two examples in which generics become an unecessary pain, and I wonder if there is a solution.
Example 1
public class SomeClass<TDbConnection, TDbTransaction>
{
}
Now for any of us it's obvious - The DbTransaction, and DbConnection implementations will always be used in pairs - be it SqlConnection and SqlTransaction or OracleConnection and OracleTransaction
besides the fact that there is no way to make sure that the types make sense (nothing stops me from creating SomeClass<SqlConnection, OracleTransaction> when SomeClass uses three or four arguments that there types are inferable by context*, it becomes an unnecessary waste of time to instantiate each type.
*in this example, I am not sure how the framework can know, but you get my point? anyway the next example is more relevant
Example 2
public interface IPoco<TKey>
{
public TKey Id { get; set; }
}
public class SomePOCO : IPoco<int>
{
public int Id { get; set; }
}
public class SomeClassUsingPOCOAndId<TPoco, TKey>
where TPoco : IPoco<TKey>
{
}
In this example I managed to force the use of the correct TKey in instantiation, but why can't I just call new SomeClass<IPoco<int>>() or new SomeClass<SomePoco>() I mean the TKey is inferable.
Possible Solutions
I could drop the Generics, and in some cases it makes sense (like the first example). In others not so much, and creates either a memory or runtime overhead (unnecessarily creating of fields, or casting) or unnecessary code repeat.
The other solution I thought of was creating something like this
public interface IPoco<TKey>
{
public TKey Id { get; set; }
}
public class SomePOCO : IPoco<int>
{
public int Id { get; set; }
}
public class PocoContext<TPoco, TKey>
where TPoco : IPoco<TKey>
{
TKey Key { get; set; }
TPoco Poco { get; set; }
public PocoContext(TPoco poco)
{
Key = poco.Key;
Poco = poco;
}
}
public class SomeClassUsingPOCOAndId<TPocoContext>
{
}
This allows me to reduce the amount of code required for instantiation - but depending on my usage of the pocos - it could become really time consuming to create a context for each type.
Now I am wondering - isn't there a way to simplify this process? maybe by some sort of synthetic sugar? What would it take to implement it on C# 7 or 8?
I have made a weather app that receives information from an api. I have a class like that:
public class Forecast
{
public DateTime date { get; set; }
public string day_name { get; set; }
public string symbol { get; set; }
public int degree { get; set; }
public int degreemax { get; set; }
public int degreemin { get; set; }
public string condition { get; set; }
}
The class helps me to hold data. Also I can hold data with ArrayList, not necessarily class. I know that I should use classes. However, I am wondering which one is more efficient.
Thanks a lot.
In your scenario, anytime I would prefer a class over an ArrayList. The following are the positives I can think of right now
Intellisense - you will have date, etc in intellisnse. Whereas in arraylist you would need to remember on which location you have entered what data
boxing-unboxing - arraylist adds values in object so if you are putting int values, they will be boxed
Multiple Forecasts - If you want to store many Forcasts then it is not possible using arraylist or at least it will be 1 hell of a time for you to maintain it. It can be easily implemented with classes using List<yourClass>
Performance - Class is anytime better performing than ArrayList
More functionality - You can add methods to a class to extend its functionality like some calculations, etc. To have more functionality to ArrayList you would need to create a custom class inheriting from ArrayList and write your functionality there so ultimately you are using a class only.
OOPS concepts - All OOPS concept apply to a class like inheritance hence extending the functionality to other classes, etc. Not possible with ArrayList
Hope this helps.
I have 3 classes, two inherit from 1:
public class Employee {
private virtual double getBonus() { ... }
private virtual double getSalary() { ... }
}
public class Nepotism : Employee {
private double getBonus() { ... }
}
public class Volunteer : Employee {
private double getSalary() { ... }
}
So the question is sometimes there will be a Volunteer who gets the Nepotism bonus - is there some way to write the constructors to allow overriding/nesting the base class like this:
Employee Bill = new Volunteer(new Nepotism());
I'm thinking something like:
public class Volunteer : Employee {
private Employee _nest;
public Volunteer(Employee nest)
: base() {
_nest = nest;
// now what?
}
}
Basically I want some objects to have the overrides from both classes.
I would like to avoid writing the override methods to check for nested classes.
getSalary() {
return (nest != null) ? nest.salary : salary; // I want to avoid this if I can
}
How can I do this? Am I on the right track? Am I off the rails?
Instead of subclassing, you might want to consider using the Decorator Pattern.
It provides an alternative to subclassing, and it useful when you may need to add "multiple" pieces of additional functionality to a single instance of a class, which is exactly the scenario.
I think you are trying to use inheritance in an ill-advised way. This approach creates a mess of dependences and oddball business rules, which results in a rigid architecture that is hard to use and maintain.
If calculating an employees salary is dependent upon the Employee as well as "bonus traits", then it would be better to separate all three things from each other:
interface IBonusTrait
{
decimal ApplyBonus(Employee employee, decimal currentTotal);
}
class Employee
{
// ...
public decimal BaseSalary { get; set; }
public IList<IBonusTrait> BonusTraits { get; set; }
}
class SalaryCalculator
{
public decimal CalculateSalary(Employee employee)
{
decimal totalSalary = employee.BaseSalary;
foreach (IBonusTrait bonusTrait in employee.BonusTraits)
{
totalSalary = bonusTrait.ApplyBonus(employee, totalSalary);
}
return totalSalary;
}
}
If an object can be both classes at once, then you may need to rethink how you're doing your inheritance.
It seems to me that if a Volunteer can sometimes get a Nepotism bonus, then really, your Volunteer class should have a getBonus() method, and this method really belongs in the base class. It would return zero for most volunteers, but occasionally it wouldn't - there's nothing wrong with that.
Reed Copsey already said, that Decorator Pattern is something to consider.
There is also this youtube video which is very similar to your case (John Skeet is presenting it).
If i have the following code example:
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA : ClassBase
{
public int JustNumber { get; set; }
public ClassA()
{
this.ID = 0;
this.Name = string.Empty;
this.JustNumber = string.Empty;
}
}
What should I do to hide the property Name (Don't shown as a member of ClassA members) without modifying ClassBase ?
I smell a code smell here. It is my opinion that you should only inherit a base class if you're implementing all of the functionality of that base class. What you're doing doesn't really represent object oriented principles properly. Thus, if you want to inherit from your base, you should be implementing Name, otherwise you've got your inheritance the wrong way around. Your class A should be your base class and your current base class should inherit from A if that's what you want, not the other way around.
However, not to stray too far from the direct question. If you did want to flout "the rules" and want to continue on the path you've chosen - here's how you can go about it:
The convention is to implement the property but throw a NotImplementedException when that property is called - although, I don't like that either. But that's my personal opinion and it doesn't change the fact that this convention still stands.
If you're attempting to obsolete the property (and it's declared in the base class as virtual), then you could either use the Obsolete attribute on it:
[Obsolete("This property has been deprecated and should no longer be used.", true)]
public override string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
(Edit: As Brian pointed out in the comments, the second parameter of the attribute will cause a compiler error if someone references the Name property, thus they won't be able to use it even though you've implemented it in derived class.)
Or as I mentioned use NotImplementedException:
public override string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
However, if the property isn't declared as virtual, then you can use the new keyword to replace it:
public new string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
You can still use the Obsolete attribute in the same manner as if the method was overridden, or you can throw the NotImplementedException, whichever you choose. I would probably use:
[Obsolete("Don't use this", true)]
public override string Name { get; set; }
or:
[Obsolete("Don't use this", true)]
public new string Name { get; set; }
Depending on whether or not it was declared as virtual in the base class.
While technically the property won't be hidden, one way to strongly discourage its use is to put attributes on it like these:
[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
This is what System.Windows.Forms does for controls that have properties that don't fit. The Text property, for instance, is on Control, but it doesn't make sense on every class that inherits from Control. So in MonthCalendar, for instance, the Text property appears like this (per the online reference source):
[Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
get { return base.Text; }
set { base.Text = value; }
}
Browsable - whether the member shows up in the Properties window
EditorBrowsable - whether the member shows up in the Intellisense dropdown
EditorBrowsable(false) won't prevent you from typing the property, and if you use the property, your project will still compile. But since the property doesn't appear in Intellisense, it won't be as obvious that you can use it.
Just hide it
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA : ClassBase
{
public int JustNumber { get; set; }
private new string Name { get { return base.Name; } set { base.Name = value; } }
public ClassA()
{
this.ID = 0;
this.Name = string.Empty;
this.JustNumber = 0;
}
}
Note: Name will still be a public member of ClassBase, given the constraint of not changing the base class there is no way to stop that.
Why force inheritance when it's not necessary?
I think the proper way of doing it is by doing has-a instead of a is-a.
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA
{
private ClassBase _base;
public int ID { get { return this._base.ID; } }
public string JustNumber { get; set; }
public ClassA()
{
this._base = new ClassBase();
this._base.ID = 0;
this._base.Name = string.Empty;
this.JustNumber = string.Empty;
}
}
I don’t think a lot of the people replying here understand inheritance at all. There is a need to inherit from a base class and hide its once public var’s and functions. Example, lets say you have a basic engine and you want to make a new engine that is supercharged. Well, 99% of the engine you will use but you will tweak a bit of its functionality to make it run much better and yet still there is some functionality that should only be shown to the modifications made, not the end user. Because we all know that every class MS puts out doesn’t really ever need any modifications.
Besides using the new to simply override the functionality it is one of the things that Microsoft in their infinite wis….. oh, I mean mistakes considered a tool not worthwhile anymore.
The best way to accomplish this now is multi-level inheritance.
public class classA
{
}
public class B : A
{}
public class C : B
{}
Class B does all your work and class C exposes what you need exposed.
You can't, that's the whole point of inheritance: the subclass must offer all methods and properties of the base class.
You could change the implementation to throw an exception when the property is called (if it were virtual)...
I completely agree that properties should not be removed from base classes, but sometimes a derived class might have a different more appropriate way to enter the values. In my case, for example, I am inheriting from ItemsControl. As we all know, ItemsControl has the ItemsSource property, but I want my control to merge data from 2 sources (for example, Person and Location). If I were to have the user enter the data using ItemsSource, I would need to separate and then recombine the values, so I created 2 properties to enter the data. But back to the original question, this leaves the ItemsSource, which I do not want the user to use because I am "replacing" it with my own properties. I like the Browsable and EditorBrowsable ideas, but it still does not prevent the user from using it. The basic point here is that inheritance should keep MOST of the properties, but when there is a large complex class (especially ones where you cannot modify the original code), rewriting everything would be very inefficient.
You can use Browsable(false)
[Browsable( false )]
public override string Name
{
get { return base.Name; }
set { base.Name= value; }
}
I think it is bad design if you have to do this, especially if you are able to design the code from the ground up.
Why?
Good design is to let the base-class share common properties that a certain concept has (virtual or real). Example: System.IO.Stream in C#.
Further down the lane bad design will increase the cost for maintenance and make implementation harder and harder. Avoid this as much as possible!
Basic rules which I use:
Minimize the number of properties and methods in the base-class. If you do not expect to use some properties or methods in a class that inherits the base class; do not put it in the baseclass then. If you are in the developmentstage of a project; always go back to the drawing-board now an then to check the design because things change! Redesign when needed. When your project is live the costs for changing things later in the design will go up!
If you are using a baseclass implemented by a 3:rd party, consider "go up" one level instead of "overriding" with "NotImplementedException" or such. If there is no other level, consider design the code from scratch.
Always consider to seal classes you do not want anyone to be able to inherit it. It forces coders to "go up one level" in the "inheritance- hierarchy" and thus "loose ends" like "NotImplementedException" can be avoided.
I know that the question is old, but what you can do is override the PostFilterProperties like this:
protected override void PostFilterProperties(System.Collections.IDictionary properties)
{
properties.Remove("AccessibleDescription");
properties.Remove("AccessibleName");
properties.Remove("AccessibleRole");
properties.Remove("BackgroundImage");
properties.Remove("BackgroundImageLayout");
properties.Remove("BorderStyle");
properties.Remove("Cursor");
properties.Remove("RightToLeft");
properties.Remove("UseWaitCursor");
properties.Remove("AllowDrop");
properties.Remove("AutoValidate");
properties.Remove("ContextMenuStrip");
properties.Remove("Enabled");
properties.Remove("ImeMode");
//properties.Remove("TabIndex"); // Don't remove this one or the designer will break
properties.Remove("TabStop");
//properties.Remove("Visible");
properties.Remove("ApplicationSettings");
properties.Remove("DataBindings");
properties.Remove("Tag");
properties.Remove("GenerateMember");
properties.Remove("Locked");
//properties.Remove("Modifiers");
properties.Remove("CausesValidation");
properties.Remove("Anchor");
properties.Remove("AutoSize");
properties.Remove("AutoSizeMode");
//properties.Remove("Location");
properties.Remove("Dock");
properties.Remove("Margin");
properties.Remove("MaximumSize");
properties.Remove("MinimumSize");
properties.Remove("Padding");
//properties.Remove("Size");
properties.Remove("DockPadding");
properties.Remove("AutoScrollMargin");
properties.Remove("AutoScrollMinSize");
properties.Remove("AutoScroll");
properties.Remove("ForeColor");
//properties.Remove("BackColor");
properties.Remove("Text");
//properties.Remove("Font");
}