I know what the use of virtual methods is, and how to declare them. But my question is: When should I declare a property as virtual?
For example:
public class Base
{
public virtual string lastName { get; set; }
}
As comments below this question state, data members are in fact methods, so you can declare them as virtual.
With properties you can add some validation later on, or implement events, for example when you implement INotifyPropertyChange interface.
Code from MSDN:
class MyBaseClass
{
public virtual string Name { get; set; }
}
class MyDerivedClass : MyBaseClass
{
private string name;
// Override auto-implemented property with ordinary property
// to provide specialized accessor behavior.
public override string Name
{
get
{
return name;
}
set
{
if (value != String.Empty)
{
name = value;
}
else
{
name = "Unknown";
}
}
}
}
Rules are the same, since property is, generally speaking, a syntactic sugar to hide get and set methods:
public class Base {
public virtual string LastName {
get; // this is method (.Net implements it for you)
set; // this is method (.Net implements it for you)
}
}
Imagine
Base b = ...
...
b.LastName = b.LastName + "x";
and compare, please, with Java which doesn't have properties:
b.setLastName(b.getLastName() + "x");
For the class in the question you may want to implment something like this:
public class Derived: Base {
public override string LastName {
get {
return String.IsNullOrEmpty(base.LastName)
? base.LastName
: base.LastName.ToUpper();
}
set {
if (null == value)
throw new ArgumentNullException("value")
base.LastName = value;
}
}
Related
I've always had this question, but I've blindly followed on so far.
This is from a piece of example code:
Why do this:
public class EmployeeInfo
{
int _EmpNo;
public virtual int EmpNo
{
get { return _EmpNo; }
set { _EmpNo = value; }
}
string _EmpName;
public virtual string EmpName
{
get { return _EmpName; }
set { _EmpName = value; }
}
}
when there's nothing additional, such as calculations or validations, being done during getting/setting?
Will this suffice?
public class EmployeeInfo
{
public int EmpNo { get; set; }
public string EmpName { get; set; }
}
Also, why virtual for the public member wrappers?
Why do this?
There's really no reason to since the addition of auto-implemented properties in C# 3.0. It could be legacy code that hasn't been changed, old habits, or keeping consistency with pre-C# 3 code.
Will this suffice?
No - you've converted the virtual properties to non-virtual. So they are not completely equivalent.
The equivalent would be
public class EmployeeInfo
{
public virtual int EmpNo { get; set; }
public virtual string EmpName { get; set; }
}
Also, why virtual for the public member wrappers?
So that a derived class can override the logic for the properties - to add validation, change notification, etc.
When does the shortened form actually have an impact?
When the backing fields are referenced by the internal code of the class (which can be detected at compile-time), or when they're accessed by reflection (which cannot be detected until run-time, or via static code analysis).
An "auto-implemented" property actually gets a backing field created by the compiler, so in that sense they're equivalent if the only place the backing field is referenced is within the property code.
You have two questions. First is changing properties to auto implemented properties, they should be equal, but you removed virtual keyword, that makes them different.
So, what is virtual. That keyword will allow derived classes to override the get/set for the said property.
See: virtual C#
The virtual keyword is used to modify a method, property, indexer, or
event declaration and allow for it to be overridden in a derived
class.
Your class with auto-implemented properties would be equal if you have:
public class EmployeeInfo
{
public virtual int EmpNo { get; set; }
public virtual string EmpName { get; set; }
}
Later you can override a property and leave the other to maintain the parent behaviour, like:
public class ManagerInfo : EmployeeInfo
{
private int _EmpNo;
public override int EmpNo
{
get { return _EmpNo; }
set
{
if (value < 100) throw new Exception("EmpNo for manager must be greater than 100");
_EmpNo = value;
}
}
}
Depends if you want to see the field publicly or not,
if your only going to use the field inside the declaring class then you don't need to wrap it in a property, its only if you need to expose it publicly or down the inheritance tree that you should have the property
public string EmpName { get; set; }
is just a compiler short cut to
private string _EmpName;
public string EmpName {
get{ return _EmpName;}
set(_EmpName = value; }
}
they are functionally identical.
However there are things that the short cut wont let you do, for example you want to raise an event when the property changes.
there there is also your use of Virtual which is an inheritance modifier
Virtual instructs the code that it needs to look DOWN the inheritance tree for a newer implementation.
so in
class A
{
public string Data
{
get{return "A";}
}
public virtual string VData
{
get{return "A";}
}
}
class B:A
{
public new string Data
{
get{return "B";}
}
public override string VData
{
get{return "B";}
}
}
then if you do
A obj = new B();
obj.Data; //return A
obj.VData; //return B
It looks like the code in this form:
$type _$var;
public virtual $type $var
{
get { return _$var; }
set { _$var = value; }
}
Was generated using a tool, template or snippet. As habits hardly ever change and tools, templates and snippets hardly ever get updated, I guess they were created before auto-implemented properties (public $type $var { get; set; }) were introduced to the C# language.
For the code you show, it's perfectly valid to have the equivalent:
public virtual $type $var { get; set; }
As you can override the auto-implemented property and add a backing field, validation and whatever when required.
The expanded form is the traditional way to do it:
public class MyClass
{
int _myInt;
virtual public int MyProperty
{
get
{
return _myInt;
}
set
{
_myInt = value;
}
}
}
However, the shorter form is called "auto properties", introduced in C# 3.0.
public class MyClass
{
virtual public int MyProperty { get; set; }
}
These code blocks are equivalent. This is a good practice for keeping your code concise.
One thing to consider: You aren't able to make the internal variable protected with auto properties, so if you create a derived class and override your property, you'll need to use base.MyProperty to access it, or use the expanded form.
I want to create a class that can take different types of value in a property. I am trying to do this using polymorphism, but I am not still learning how to do this properly, hence my request for advice.
I have a base class and two classes that inherit from it:
public abstract class BaseClass
{
public string Name { get; set; }
public Unit Unit { get; set; }
}
public class DerivedClassFloat : BaseClass
{
public float Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
All is good, I can create a List and add different specialized subclasses. My problem comes when I need change the values of the items in my list:
foreach (var item in ListOfBaseClasses)
{
if(item is DerivedClassFloat)
((DerivedClassFloat) item).Value = float.NaN;
if (item is DerivedClassString)
((DerivedClassString) item).Value = string.Empty;
}
According to what I have read, that looks like a code smell. Is there a better way to access the value property of my derived classes based on the type I am trying to assign?
What about when you want to create the right subclass based on the value?
BaseClass newClass = null;
if (phenotype is DerivedClassFloat)
newClass = new DerivedClassFloat(){Value = 12.2};
if (phenotype is DerivedClassString)
newClass = new DerivedClassString(){Value = "Hello"};
I read about overriding virtual methods, but that works if I want to process the value, not to add or change it … maybe I am missing something?
I should make this more concrete, my apologies, I am not used to post question in this great site.
I need a property that is made of a list of attributes. Each attribute has a name and a value, but the value can be of different types. For example:
public class Organism
{
public string Name { get; set; }
public List<Attribute> Attributes { get; set; }
}
public class Attribute
{
public string AttributeName { get; set; }
public object AttributeValue { get; set; }
}
For a given organism I can have several attributes holding different value types. I wanted to avoid using the object type so that I don’t have to cast to the right type. I though property polymorphism was the solution to handle this case elegantly, but then I found myself using If ..Then which didn’t seem too different from casting in the first place.
If in your particular case you want to reset Value, you can define an abstract ResetValue method in the base class, which will be implemented by the derives classes.
As for your second case, you should check out Creational Design Patterns, and specifically the Factory and Prototype design patterns.
You can use generics to define the type and the implementing subclass will set the Value type to the type constraint:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedFloat : BaseClass<float> {}
public class DerivedString : BaseClass<string> {}
You can use Generics for this particular case:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
}
public class DerivedClassFloat : BaseClass<float>
{
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass<string>
{
public override string ToString()
{
return Value;
}
}
Polymorphic behaviour works on abstraction. Based on what your trying to do, you can reduce code smell to moving as much of your variability in code to base classess.
i would suggest is instead of property write method like as follows. You can something like as follows.
public void setValue(string val, Type type);//move this to your base class
Class MyValue{
private string strVal;
private int intVal;
//constructor
MyValue(string val, Type type){
//check the type enum here and set the values accordingly
}
}
then when set values
foreach (var item in ListOfBaseClasses)
{
item.setValue = MyValue("",Type.INT);
}
I'm not quite sure what you are trying to achieve with this approach - the Value properties are not of the same type, there is also no Value property on the base class which suggests that other types derived from the base class might not have it at all.
If all of your classes require a Value property, then maybe it should be of the most general type object - you could put it onto the base class, but that would require casting the values in the derived classes.
But then you could have a NullObject to represent an absence of value that you could assign to the Value property for every derived class.
You can use the abstract factory pattern. Consider this example:
// Base class
class Button
{
protected Button()
{
}
public string Name { get; set; }
}
// Factory interface
public interface ButtonFactory
{
Button CreateButton();
}
// And the concrete classes
class WindowsButton : Button
{
// ...
}
class WindowsButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new WindowsButton();
}
}
class MacButton : Button
{
// ...
}
class MacButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new MacButton();
}
}
Furthermore, you can combine the abstract factory pattern with the strategy pattern to encapsulate the custom behaviors that change with type.
I would like to force a set of classes to define three fields (of type string).
In an abstract class, I get that fields cannot be abstract and in an interface, I get an error saying that an interface cannot contain a field.
Is there no way to do this or am I not understanding this correctly? I'd rather not use methods because for some weird reason, the parentheses annoy me.
You can use properties for that:
interface MyInterface {
string Prop1 { get; set; }
string Prop2 { get; set; }
string Prop3 { get; set; }
}
Interface or abstract members force derived classes to provide code.
Fields don't have code.
You should use a property, which can be used like a field, but has code.
You can use Properties instead of fields:
// works similarly for Interfaces too
abstract class MyAbstractClass { public virtual string MyProperty1 { get; set; } }
class MyConcreteClass : MyAbstractClass { }
Then you can access MyProperty1 from any instance derived from MyAbstractClass:
MyAbstractClass obj1 = new MyConcreteClass;
obj1.MyProperty1 = "abcd";
Like everyone else says, use properties instead of fields, but you can do something like I interpreted in the comments as follows for read-only members:
abstract public class Base
{
abstract public string Foo { get; }
abstract public string Bar { get; }
abstract public string Baz { get; }
}
public class Derived : Base
{
public override string Foo { get { return "foo"; } }
public override string Bar { get { return "bar"; } }
public override string Baz { get { return "baz"; } }
}
If you want the fields to be modifiable later, you'll have to either use automatic properties or declare concrete backing fields and getter/setter pairs for each property.
This question already has answers here:
Collection of generic types
(10 answers)
Closed 7 years ago.
I have an object (form) which contains a collection (.Fields) which I want to contain instances of a generic class (FormField).
The FormField, simply, is defined as such:
public class FormField<T>
{
private Form Form;
public T Value { get; set; }
public string Name { get; set; }
public void Process()
{
// do something
}
public FormField(Form form, string name, T value)
{
this.Name = name;
this.Value = value;
this.Form = form;
}
}
This allows me to have FormField, FormField etc. and that part works great.
What I want is a collection of "Formfields" regardless of the type, but I am forced into defining a type (it seems) such as:
public class Form
{
string Code { get; set; }
string Title { get; set; }
int Year { get; set; }
Guid ClientID { get; set; }
ICollection<FormField<int>> Fields { get; set; }
}
What, I think, I want is an interface that allows me to abstract the type information and thus type the collection as instances of (for exxample) IFormField not FormField<>
But I can't see how to define this without strongly typing the collection in the interface...
Any help (including any alternative solutions!) would be greatly appreciated!
Thanks, Ben
Here's some code to complete Jon's answer:
public interface IFormField
{
string Name { get; set; }
object Value { get; set; }
}
public class FormField<T> : IFormField
{
private Form Form;
public T Value { get; set; }
public string Name { get; set; }
public void Process()
{
// do something
}
public FormField(Form form, string name, T value)
{
this.Name = name;
this.Value = value;
this.Form = form;
}
// Explicit implementation of IFormField.Value
object IFormField.Value
{
get { return this.Value; }
set { this.Value = (T)value; }
}
}
And in your form:
ICollection<IFormField> Fields { get; set; }
Create a non-generic interface or base class, which probably includes everything FormField does except the type-specific bits. Then you can have an ICollection<IFormField>. Obviously you won't be able to use this in a strongly-typed way, in terms of the type of field being used - but you can use all the non-type-specific bits of it (e.g. the name and the form).
Another option (an alternative to Jon's answer) is to apply the adapter pattern, which can be useful when:
you are unable to modify the type, and can thus not define a base-type for it.
or, there is a need to expose 'type-specific bits' (as Jon put it).
When you want to expose type-specific bits, you effectively have to create a non-generic wrapper. A short example:
class NonGenericWrapper<T> : IAdaptor
{
private readonly Adaptee<T> _adaptee;
public NonGenericWrapper(Adaptee<T> adaptee)
{
_adaptee = adaptee;
}
public object Value
{
get { return _adaptee.Value; }
set { _adaptee.Value = (T) value; }
}
}
Implementing this non-generic behavior in a base-type would effectively break the Liskov substitution principle, which is why I prefer the wrapper approach as I also argue in my blog post.
I have interface IResourcePolicy containing the property Version. I have to implement this property which contain value, the code written in other pages:
IResourcePolicy irp(instantiated interface)
irp.WrmVersion = "10.4";
How can I implement property version?
public interface IResourcePolicy
{
string Version
{
get;
set;
}
}
In the interface, you specify the property:
public interface IResourcePolicy
{
string Version { get; set; }
}
In the implementing class, you need to implement it:
public class ResourcePolicy : IResourcePolicy
{
public string Version { get; set; }
}
This looks similar, but it is something completely different. In the interface, there is no code. You just specify that there is a property with a getter and a setter, whatever they will do.
In the class, you actually implement them. The shortest way to do this is using this { get; set; } syntax. The compiler will create a field and generate the getter and setter implementation for it.
You mean like this?
class MyResourcePolicy : IResourcePolicy {
private string version;
public string Version {
get {
return this.version;
}
set {
this.version = value;
}
}
}
Interfaces can not contain any implementation (including default values). You need to switch to abstract class.
The simple example of using a property in an interface:
using System;
interface IName
{
string Name { get; set; }
}
class Employee : IName
{
public string Name { get; set; }
}
class Company : IName
{
private string _company { get; set; }
public string Name
{
get
{
return _company;
}
set
{
_company = value;
}
}
}
class Client
{
static void Main(string[] args)
{
IName e = new Employee();
e.Name = "Tim Bridges";
IName c = new Company();
c.Name = "Inforsoft";
Console.WriteLine("{0} from {1}.", e.Name, c.Name);
Console.ReadKey();
}
}
/*output:
Tim Bridges from Inforsoft.
*/
but i already assigned values such that irp.WrmVersion = "10.4";
J.Random Coder's answer and initialize version field.
private string version = "10.4';
You should use abstract class to initialize a property. You can't inititalize in Inteface .