Context: a simple base class which holds a name and a couple methods.
public abstract class BaseElement
{
public string Name { get; set; }
public abstract object GetDescription();
public abstract void DoStuff();
}
A developer could subclass BaseElement, he will have to implement GetDescription() and DoStuff(), but can completely forget to assign a value to the Name property.
A simple solution would be to change the class this way:
public abstract class BaseElement
{
public string Name { get; private set; }
public abstract object GetDescription();
public abstract void DoStuff();
private BaseElement()
{
}
public BaseElement(string name)
{
Name = name;
}
}
So, this way when you subclass you are forced to assign a name.
Still, you can always go as far as to use null or "".
Ok, then I can add a parameter check into the ctor and throw the relative exception, but...you'll discover the mistake only at run time, after you try to use the derived class.
So, the question: is it possible to add compilation-time rules to instruct the compiler to check for variables possible values, so that the problem is discovered at compile time and not at run time?
How about like this?
public string Name
{
get { return _name; }
private set
{
if (!string.IsNullOrWhiteSpace(value))
_name = value;
else
{
throw new Exception("Exception");
}
}
}
Related
I have many classes that have the following members/methods:
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public bool isNamed(String name) { return getName().Equals(name); }
Every time I create a new class that has a member "name", I have to rewrite all these.
Is there a way to write the methods one time and to make them apply to any class I want?
Your code can be converted to:
public String Name { get;set;}
Then you can use it as so:
nObject.Name = "Stefan";
if(nObject.Name == "Stefan"){
// do something
}else{
// do something else
}
To apply to all the classes automatically you can just make this into an interface:
public interface INameable{
public String Name {get;set;}
}
Doing this will allow you to inherit from other base classes of importance.
see here for an example
class YourClass : INameable{
//implementation
}
And now, YourClass has "Name" property automatically inserted.
You'd simply define a base class (you could make it abstract):
public abstract class Named
{
public string Name { get; set; }
}
and inherit from it:
public class Person : Named
{
}
You don't really need isNamed as in C#, it is perfectly safe to compare strings with ==.
If your class already inherits from another class which is not Named, you'll have to manually add the Name auto property or resort to simulated multiple inheritance.
Alternatively, you could create a specific modification of Named for every base class:
public abstract class NamedLifeForm : LifeForm
{
public string Name { get; set; }
}
public class Person : NamedLifeForm
{
// Person inherits both a Name and all relevant members of LifeForm
}
Another alternative would be to create a generic wrapper, Named<T>, that would have two properties: the Name and an instance of T. But that would make construction and access cumbersome, so I don't recommend it.
C# has AutoProperties just for that:
public String Name {get; set; }
This handles both the getName() and the setName() you talked about.
Usage:
To set a value: Name = "MyName;
To get a value: string theName = Name;
I'd suggest reading up on Object Oriented Programming. You can save yourself a lot of time and effort (and heckling). Here is a good primer http://www.amazon.com/Beginning-Object-Oriented-Programming-Dan-Clark/dp/1430235306
To answer your specific question, you should read about inheritance. It lets you define a "Parent" class with functions. Then you can inherit with "Child" classes and have those same functions.
http://msdn.microsoft.com/en-us/library/ms173149(v=vs.80).aspx
Here is a code example
public class PersonBase
{
private String name;
public String getName()
{
return this.name;
}
public void setName(string name)
{
this.name = name;
}
public bool isNamed(string name)
{
return this.name.Equals(name);
}
}
public class Employee : PersonBase
{
}
Employee will now have whatever was defined by PersonBase.
As others have pointed out, you can simplify you code with properties. Also you should check for null values before using "this.name".
Here is a link to what properties are:
http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx
The simplified code example would be:
public class PersonBase
{
public String Name { get; set; }
}
public class Employee : PersonBase
{
}
I hope this helps get you pointed in the right direction for learning about these concepts.
I'm designing a data layer for several classes, and I want each of these classes to follow a contract I set up with IMyDataItem:
public delegate void ItemChangedHandler(object sender, EventArgs e);
public interface IMyDataItem<T> {
string Insert { get; }
int Save();
string Select { get; }
string Update { get; }
}
That being done, I now want to include a base class that my other classes all inherit from.
How would I fix this base class?
public class MyDataItem : IMyDataItem<T> {
private const string TODO = "TODO: This has not been done.";
public const int NOT_SET = -1;
private bool changed;
internal int rowId;
public MyDataItem() {
changed = false;
rowId = NOT_SET;
}
public ItemChangedHandler OnChange;
internal void notify() {
changed = true;
if (OnChange != null) {
OnChange(this, new EventArgs());
}
}
public int RowID {
get { return rowId; }
set {
if (rowId != value) {
rowId = value;
notify();
}
}
}
public bool SaveNeeded { get { return changed; } }
public static virtual T Load() {
return default(T);
}
public virtual string Insert { get { return TODO; } }
public virtual string Select { get { return TODO; } }
public virtual string Update { get { return TODO; } }
public virtual int Save() {
changed = false;
return NOT_SET;
}
}
The errors are all in the second class MyDataItem (my base class):
Type or namespace name 'T' could not be found - on the first line where I declare my class.
I tried removing the errors by adding a where clause to the signature:
public class MyDataItem : IMyDataItem<T> where T : MyDataItem {
However, this presented me with the error:
Constraints are not allowed on non-generic declarations
Is there a way to do what I am after, or will I need to stick with simpler class designs?
When the base class is complete, other classes such as Location, Employee, and Record will inherit it.
Well to fix that particularly compile time error you would need:
public class MyDataItem<T> : IMyDataItem<T>
However, without knowing more about what you're trying to achieve, it's hard to recommend an alternative approach.
Why not drop the <T> from the interface and make it non-generic? The T is not used in the interface.
Otherwise, if you want the class to be generic, say
public class MyDataItem<T> : IMyDataItem<T>
But again, if T is not used, what's your reason to declare it?
What you are attempting to do is somewhat similar to what I've also done. I've wanted some generic code applicable to all my "data manager" instances but also wanted to apply stronger typing to them... In a similar fashion...
public interface iMyDataManager
{
stuff ...
}
public class MyDataManager<T> : iMyDataManager
{
implementation ... that I want common to all derived specific instances
}
public class MySpecificDataInstance : MyDataManager<MySpecificDataInstance>
{
continue with rest of actual implementations specific to this class.
}
I did not see any reason use generic in your implementation.
Secondary, are you sure about parameters of these functions:
string Insert { get; }
int Save();
string Select { get; }
string Update { get; }
Why Update and Insert returns parameters? Are you sure, you will able remember meaning of this within 2 months?
I have a "simple" problem, and I crated an example app to illustrate. I would like the b.getName() call to return "barname", but it does not, and I'm not sure how to get this to work. I've been working in C# for years, but at the moment I feel like a newbie because this late binding problem has me stumped.
class Program
{
static void Main(string[] args)
{
bar b = new bar();
Console.WriteLine(b.getName());
Console.ReadLine();
}
}
class foo
{
string name = "fooname";
public string getName()
{
return this.name;
}
}
class bar:foo
{
string name = "barname";
}
By default your name variable is private - it sounds like you want it to be protected, so you can overwrite the value - this would work:
class foo
{
protected string name = "fooname";
public string getName()
{
return this.name;
}
}
class bar : foo
{
public bar()
{
name = "barname";
}
}
If you're not married to having a private class variable, you can accomplish this with an overridden property:
class foo
{
public virtual string Name
{
get
{
return "fooname";
}
}
}
class bar : foo
{
public override string Name
{
get
{
return "barname";
}
}
}
This isn't related to late binding. Late binding generally refers to calling a method at runtime from the name.
What your supplied code actually does is create a new variable that's in a different scope than what your base class has access to.
In order to get the desired effect, you actually need to either 1) make the base class method implementation virtual, and override the method in your child, or 2) in your base class change your variable to have a default accessibility of protected and set the value in your derived class's constructor(s).
In my current project I need to be able to have both editable and read-only versions of classes. So that when the classes are displayed in a List or PropertGrid the user is not able to edit objects they should not be allowed to.
To do this I'm following the design pattern shown in the diagram below. I start with a read-only interface (IWidget), and then create an edtiable class which implements this interface (Widget). Next I create a read-only class (ReadOnlyWidget) which simply wraps the mutable class and also implements the read only interface.
I'm following this pattern for a number of different unrelated types. But now I want to add a search function to my program, which can generate results that include any variety of types including both mutable and immutable versions. So now I want to add another set of interfaces (IItem, IMutableItem) that define properties which apply to all types. So IItem defines a set of generic immutable properties, and IMutableItem defines the same properties but editable. In the end a search will return a collection of IItems, which can then later be cast to more specific types if needed.
Yet, I'm not sure if I'm setting up the relationships to IMutable and IItem correctly. Right now I have each of the interfaces (IWidget, IDooHickey) inheriting from IItem, and then the mutable classes (Widget, DooHickey) in addition also implement IMutableItem.
Alternatively, I was also thinking I could then set IMutableItem to inherit from IItem, which would hide its read-only properties with new properties that have both get and set accessors. Then the mutable classes would implement IMutableItem, and the read-only classes would implement IItem.
I'd appreciate any suggestions or criticisms regarding any of this.
Class Diagram
Code
public interface IItem
{
string ItemName { get; }
}
public interface IMutableItem
{
string ItemName { get; set; }
}
public interface IWidget:IItem
{
void Wiggle();
}
public abstract class Widget : IWidget, IMutableItem
{
public string ItemName
{
get;
set;
}
public void Wiggle()
{
//wiggle a little
}
}
public class ReadOnlyWidget : IWidget
{
private Widget _widget;
public ReadOnlyWidget(Widget widget)
{
this._widget = widget;
}
public void Wiggle()
{
_widget.Wiggle();
}
public string ItemName
{
get {return _widget.ItemName; }
}
}
public interface IDoohickey:IItem
{
void DoSomthing();
}
public abstract class Doohickey : IDoohickey, IMutableItem
{
public void DoSomthing()
{
//work it, work it
}
public string ItemName
{
get;
set;
}
}
public class ReadOnlyDoohickey : IDoohickey
{
private Doohickey _doohicky;
public ReadOnlyDoohickey(Doohickey doohicky)
{
this._doohicky = doohicky;
}
public string ItemName
{
get { return _doohicky.ItemName; }
}
public void DoSomthing()
{
this._doohicky.DoSomthing();
}
}
Is it OK to create another object when you need a readonly copy? If so then you can use the technique in the included code. If not, I think a wrapper is probably your best bet when it comes to this.
internal class Test
{
private int _id;
public virtual int ID
{
get
{
return _id;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
private string _name;
public virtual string Name
{
get
{
return _name;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
public bool ReadOnly { get; private set; }
public Test(int id = -1, string name = null)
: this(id, name, false)
{ }
private Test(int id, string name, bool readOnly)
{
ID = id;
Name = name;
ReadOnly = readOnly;
}
public Test AsReadOnly()
{
return new Test(ID, Name, true);
}
}
I would suggest that for each main class or interface, there be three defined classes: a "readable" class, a "changeable" class, and an "immutable" class. Only the "changeable" or "immutable" classes should exist as concrete types; they should both derive from an abstract "readable" class. Code which wants to store an object secure in the knowledge that it never changes should store the "immutable" class; code that wants to edit an object should use the "changeable" class. Code which isn't going to write to something but doesn't care if it holds the same value forever can accept objects of the "readable" base type.
The readable version should include public abstract methods AsChangeable(), AsImmutable(), public virtual method AsNewChangeable(), and protected virtual method AsNewImmutable(). The "changeable" classes should define AsChangeable() to return this, and AsImmutable to return AsNewImmutable(). The "immutable" classes should define AsChangeable() to return AsNewChangeable() and AsImmutable() to return this.
The biggest difficulty with all this is that inheritance doesn't work terribly well if one tries to use class types rather than interfaces. For example, if one would like to have an EnhancedCustomer class which inherits from BasicCustomer, then ImmutableEnhancedCustomer should inherit from both ImmutableBasicCustomer and ReadableEnhancedCustomer, but .net doesn't allow such dual inheritance. One could use an interface IImmutableEnhancedCustomer rather than a class, but some people would consider an 'immutable interace' to be a bit of a smell since there's no way a module that defines an interface in such a way that outsiders can use it without also allowing outsiders to define their own implementations.
Abandon hope all ye who enter here!!!
I suspect that in the long run your code is going to be very confusing. Your class diagram suggests that all properties are editable (or not) in a given object. Or are your (I'm)mutable interfaces introducing new properties that are all immutable or not, separate from the "core"/inheriting class?
Either way I think you're going to end up with playing games with property name variations and/or hiding inherited properties
Marker Interfaces Perhaps?
Consider making all properties in your classes mutable. Then implement IMutable (I don't like the name IItem) and IImutable as a marker interfaces. That is, there is literally nothing defined in the interface body. But it allows client code to handle the objects as a IImutable reference, for example.
This implies that either (a) your client code plays nice and respects it's mutability, or (b) all your objects are wrapped by a "controller" class that enforces the given object's mutability.
Could be too late :-), but the cause "The keyword 'new' is required on property because it hides property ..." is a bug in Resharper, no problem with the compiler. See the example below:
public interface IEntityReadOnly
{
int Prop { get; }
}
public interface IEntity : IEntityReadOnly
{
int Prop { set; }
}
public class Entity : IEntity
{
public int Prop { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var entity = new Entity();
(entity as IEntity).Prop = 2;
Assert.AreEqual(2, (entity as IEntityReadOnly).Prop);
}
}
Same for the case without interfaces. The only limitation, you can't use auto-properties
public class User
{
public User(string userName)
{
this.userName = userName;
}
protected string userName;
public string UserName { get { return userName; } }
}
public class UserUpdatable : User
{
public UserUpdatable()
: base(null)
{
}
public string UserName { set { userName = value; } }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var user = new UserUpdatable {UserName = "George"};
Assert.AreEqual("George", (user as User).UserName);
}
}
I have a need where I have to add some new fields to an existing class along with all its existing fields/attributes.
So whenever my derived class is filled by DAL, I will be filling all fields of base class as well. Currently, I am doing it like this but not sure this is the right way ? Please give me an example. Also I am not sure whether the base class object will be a new one each time a derived class is initialized ?
public class Employee
{
private int _id;
private int _name;
public int ID
{
set { _id=value;}
get { return _id;}
}
public int Name
{
set { _name=value;}
get { return _name;}
}
protected void SetName ()
{
_name=value;
}
protected void SetID()
{
_id=value;
}
}
public class EmployeeWithDepartmentName:Employee
{
private string _deptName;
public string DeptName
{
set { _deptName=value; }
}
public setBaseEmpName()
{
base.SetName();
}
public setBaseID()
{
base.SetID();
}
}
Everything in a base class can automagically be accessed from derived classes without doiing anything, just use the property/method name directly.
public class MyBase
{
public string UserName {get;set;}
}
public class MyClass : MyBase
{
public void DoSomething()
{
Console.WriteLine("UserName: {0}", UserName);
UserName = "Anders";
}
}
You can also do this:
MyClass myClass = new MyClass();
myClass.UserName = "Rune";
Protected means that only derived classes can access the property/method. Public means that everyone can access the properties/methods.
Also I am not sure whether the base class object will be a new one each time a derived class is initialized ?
It's not two objects, it's one object created from two different classes (that's how inheritance works).
Read this article about inheritance: http://www.csharp-station.com/Tutorials/lesson08.aspx