I have used and learned only virtual methods of the base class without any knowledge of virtual properties used as
class A
{
public virtual ICollection<B> prop{get;set;}
}
Could someone tell me what that means ?
public virtual ICollection<B> Prop { get; set; }
Translates almost directly to:
private ICollection<B> m_Prop;
public virtual ICollection<B> get_Prop()
{
return m_Prop;
}
public virtual void set_Prop(ICollection<B> value)
{
m_Prop = value;
}
Thus, the virtual keyword allows you to override the property in sub-classes just as you would the above get/set methods:
public override ICollection<B> Prop
{
get { return null; }
set { }
}
In object-oriented programming, a virtual property is a property whose behavior can be overridden within an inheriting class. This concept is an important part of the polymorphism portion of object-oriented programming (OOP).
look at the example below:
public class BaseClass
{
public int Id { get; set; }
public virtual string Name { get; set; }
}
public class DerivedClass : BaseClass
{
public override string Name
{
get
{
return base.Name;
}
set
{
base.Name = "test";
}
}
}
at the presentation level:
DerivedClass instance = new DerivedClass() { Id = 2, Name = "behnoud" };
Console.WriteLine(instance.Name);
Console.ReadKey();
the output will be "test", and not "behnoud", because the "Name" property has been overridden in the derived class(sub class).
In Entity Framework (which I believe your example refers to), your POCO classes are created and wrapped into a proxy class. Proxy class is a descendant of the class that you declare, so your class A becomes a base class. This proxy class is populated with data and returned back to you. This is necessary in order to track changes. Have a look at this article http://technet.microsoft.com/en-us/query/dd456848
I had a similar problem in trying to understand this and after a few debugging sessions and seeing the proxy classes and reading about tracking changes it made be figure out why it is declared the way it is.
Properties are actually specials cases of Getter and Setter methods. So they are like combinations of Getter and Setter methods as shown below:
private string _name;
public string GetName()
{
return _name;
}
public void SetName(string value)
{
this._name = value;
}
So virtual keyword is same for properties as well which means it is overrideable by the child classes and initial implementation can be changed.
Properties are a shortened form of accessor methods (Get & Set). That means that the virtual keyword has the same meaning as with any other method. That means you can override it in derived classes.
You can have methods (often), properties, indexers or events, the virtual keyword has the same meaning : modifying the meaning (override) of the base class item.
With properties, you can change the get/set accessors.
It's a collection that's implementation can vary in a descendant class.
Related
I created classes that derive from a parent class looking like this.
class Usability
{
public string useName = "404";
}
and
class Heal : Usability
{
public string useName = "drink";
}
when putting multiple in a Dictionary
public Dictionary<int, Usability> useDict = new();
and then accessing useName via
foreach(var usability in item.usabilitys)
{
Console.Write(usability.useName);
}
allways prints "404". When using
foreach(Heal usability in item.usabilitys)
{
Console.Write(usability.useName);
}
instead prints "drink". There are functions and more data included in sub classes but this breaks down the problem as much as possible.
useName is the field, and fields can't be inherited.
You can use the properties instead of the fields:
public class Base
{
public virtual string Name { get; } = "404";
}
public class Inheritor : Base
{
public override string Name { get; } = "drink";
}
You must mark the base property as a virtual to override it in the class Inheritor.
Properties is just syntax sugar to getter and setter methods, so the property Name is really compiled to the method get_Name.
When you mark the property as the virtual you really make virtual method get_Name and you can override it.
I'm not strong on c# interfaces, so this is me misunderstanding something.
I have this interface (PMQIdent is just an identifier at heart):
public interface IisNamedItem2 {
// note: is virtual
public virtual PMQIdent name {
get => name;
private set => name = value;
}
}
used like this:
public class TVDeclarationStatement2 : IisNamedItem2 {
// ctor
public TVDeclarationStatement2(PMQIdent nameIn) =>
name = nameIn;
}
But it complains that "the name 'name' does not exist in the current context"
As I marked the relevant part is virtual, I'd expect that to be carried into the class (edit: meaning effectively copied into the using class's definition, so it would just be there instead of me having to add it each time).
If I rewrite the interface as
public interface IisNamedItem999 {
private PMQIdent _name;
public virtual PMQIdent getName() => _name;
public virtual PMQIdent sestName(PMQIdent val) =>
_name = val;
}
It - quite reasonably - complains “Interfaces cannot contain instance fields”
What’s the right way to do this?
More importantly, what is the conceptual thing I’m missing that is making me misunderstand this?
Very helpful answers and comments all round. I've accepted Stefan's answer as it explains why I my thinking was wrong. Thanks all, and I've got some good links to read.
More importantly, what is the conceptual thing I’m missing that is making me misunderstand this?
Implementing the interface just tells the class which methods and properties it has to contain. If there is you property in the interface, it isn't automatically in your class that inherits from it. That only happens when you inherit from an other class.
So if you have PMQIdent Name { get; set; } in your interface, you also have to write PMQIdent Name { get; set; } down in your class.
"Virtual" only means, that you can override this method or property in your class. In your example you could declare an other get/set for your property, than it has in your interface. You can do this using the "override" keyword in your class that inherits from the interface.
The answer from Ivan Khorin shows you the correct code for what you want to do.
public interface IisNamedItem2
{
// note: is virtual
PMQIdent Name { get; set; }
}
public class TVDeclarationStatement2 : IisNamedItem2
{
public virtual PMQIdent Name { get; set; }
public TVDeclarationStatement2(PMQIdent nameIn)
{
Name = nameIn;
}
}
Main Question:
I have a reference type (object/class) where I would like to specify accessors' implementation details, but I don't want the type to be instantiable, only extendible.
Abstract Classes don't allow bodies to the accessors of Properties as far as I understand, so that makes it trouble some for me.
How would I go about this in the most 'correct' and elegant manner?
Second question:
I would also like functionality for overloading accessors if there is a way? One reason is that I have an enum Property, which I want to be settable by using its value (int) or its enum reference type.
Abstract Classes don't allow bodies to the accessors of Properties as far as I understand
Yes they do... this is perfectly legal
abstract class MyBaseClass
{
private int _myProperty;
public int MyProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}
}
Perhaps you're confusing abstract classes and interfaces; interfaces can declare members, but they can't provide an implementation for those members.
Abstract Classes don't allow bodies to the accessors of Properties as
far as I understand, so that makes it trouble some for me.
yes they do;
public abstract class Foo
{
public string Prop
{
get { return "yesTheyDo"; }
}
}
are you marking them abstract?
I think this should do what you want:
public abstract class MyParentClass
{
public enum MyEnum
{
one,
two,
three
}
private MyEnum _enumeration;
public string Name { get; private set; }
public MyEnum Enumeration { get { return this._enumeration; } }
public void SetEnumeration(string value)
{
// ... do something
}
public void SetEnumeration(MyEnum value)
{
// ... do something
}
}
There are two overloaded methods for setting the Enumeration property and some methods have their bodies declared whilst the whole class cannot be instantiated.
Hope that helps :)
You can define the body of methods and properties inside of an abstract class. The abstract part of it essentially just prevents it from being instantiated. To accomplish this, you would write the property as normal:
public string Name
{
get { return "SomeName"; }
}
As an example. As for allowing overloading of accessors, you could do one of the following:
// By setting this as 'virtual' you can allow classes that inherit from this to override the functionality if they so wish
public virtual string Name
{
get { return "SomeName"; }
}
// or
public virtual string GetName()
{
return "SomeName";
}
One tip: if you are wanting the functionality to be overridden and accessible only to classes that inherit the abstract class, use the protected keyword:
protected virtual void DoSomething() { }
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);
}
}
Simple question: does an abstract property create a private backing field? Example:
public abstract Name { get; set; }
Will this create a private backing field? I want to force any class that derives this property to use their own backing field, not one that's created by the compiler.
No it doesn't. I just tested with the following class:
public abstract class Class1
{
public abstract string TestStringAbstract { get; set; }
public string TestString { get; set; }
}
and decompiled it in Reflector. This was the generated code:
public abstract class Class1
{
// Fields
[CompilerGenerated]
private string <TestString>k__BackingField;
// Methods
protected Class1()
{
}
// Properties
public string TestString
{
[CompilerGenerated]
get
{
return this.<TestString>k__BackingField;
}
[CompilerGenerated]
set
{
this.<TestString>k__BackingField = value;
}
}
public abstract string TestStringAbstract { get; set; }
}
As you can see only a single backing field was generated for the concrete property. The abstract one was left as a definition.
This makes logical sense since the property must be overridden by any child class there is no point in creating a backing field that there would be no way of ever accessing (since you can't ever access the abstract property).
On the other hand a virtual property will create a backing field and any class that overrides the property with an auto-implemented replacement will create its own backing field at that class's level.
No. Since it's abstract, the class implementer must implement the property. If the implementer declares it that way, then Yes, it's an automatic property with a hidden member to hold the actual value.
There's a difference between:
public abstract string Name { get; set; }
and
public string Name { get; set; }
The first property declaration doesn't create a backing field. It just creates an abstract property (kind of like an interface method declaration), which has to be implemented by any non-abstract inheriting class.
The second declaration is an auto-property, which DOES create a backing field. It's actually compiler syntactic sugar shorthand for:
private string _name;
public string Name { get { return _name; } set { _name = value; } }