instantiating generic classes in c# - c#

In the piece of code below, the output is;
Ernie
Bert
Elmo
Why is the last output is Elmo? Shouldn't it be Ernie? Because i instantiate dog.Creature object with new Cat();. i thought that the Name property of Cat class overrides the Name property of Creature class.
class Class1
{
public static void Main(string[] args)
{
var dog = new Dog();
var cat = new Cat();
dog.Creature = new Cat();
Console.WriteLine(cat.Name); //outputs Ernie
Console.WriteLine(dog.Name); //outputs Bert
Console.WriteLine(dog.Creature.Name); //outputs Elmo, why not Ernie?
Console.Read();
}
}
public class Animal<T> where T : Creature
{
public T Creature { get; set; }
private string _name = "Oscar";
public string Name { get { return _name; } set { _name = value; } }
}
public class Creature
{
private string _name = "Elmo";
public string Name { get { return _name; } set { _name = value; } }
}
public class Cat : Creature
{
private string _name = "Ernie";
public string Name { get { return _name; } set { _name = value; } }
}
public class Dog : Animal<Creature>
{
private string _name = "Bert";
public string Name { get { return _name; } set { _name = value; } }
}

Firstly, this has nothing to do with generics. You'll get exactly the same behaviour if you write:
Creature cat = new Cat();
Console.WriteLine(cat.Name);
Don't forget that the compile-time type of Dog.Creature is Creature.
i thought that the Name property of Cat class overrides the Name property of Creature class.
No, because it's not a virtual property and you haven't used override. You should have a compile-time warning explicitly saying that you're hiding the member, not overriding it:
Test.cs(30,19): warning CS0108: 'Cat.Name' hides inherited member
'Creature.Name'. Use the new keyword if hiding was intended.
If you change Cat and Creature to be like this, it will work:
public class Creature
{
private string _name = "Elmo";
public virtual string Name { get { return _name; } set { _name = value; } }
}
public class Cat : Creature
{
private string _name = "Ernie";
public override string Name { get { return _name; } set { _name = value; } }
}
... but personally I'd try to avoid this anyway. Why not just use the setter in Creature? Why would you want there to be two _name fields in a Cat object? It's not like they're meant to serve different purposes, is it?
It's not clear what you're trying to achieve, but I'd almost certainly give the Creature class a constructor taking the name as a parameter. I'd probably make the property read-only if at all possible, too.

A good practice is to read the warnings the IDE gives you.
warning CS0108: 'Program.Cat.Name' hides inherited member 'Program.Creature.Name'. Use the new keyword if hiding was intended.
warning CS0108: 'Program.Dog.Name' hides inherited member 'Program.Animal<Program.Creature>.Name'. Use the new keyword if hiding was intended.

I thought that the Name property of Cat class overrides the Name property of Creature class
No, it hides it. You have two different properties with the same name. If you want to override it, you need to make the base property virtual and use the override keyword on the inherited class:
public class Creature
{
private string _name = "Elmo";
public virtual string Name { get { return _name; } set { _name = value; } }
}
public class Cat : Creature
{
private string _name = "Ernie";
public override string Name { get { return _name; } set { _name = value; } }
}
As to why you are seeing "Elmo" instead of "Ernie" - it's because Dog is an Animal<Creature>, so the property Dog.Creature is of type Creature. Even though you pass in a Cat, since the Name property is not overridden, Creature.Name is called. If you had overrode Name, then Cat.Name would be called instead.

Related

Set a field value in a base class that can be overridden in child classes in C#

I have a C# class that looks like this:
public class Animal
{
public string _name = "Animal";
public string GetGreeting()
{
if (this._name == "Animal")
{
return "Hello friend!";
}
else
{
return $"Hello, '{this._name}'";
}
}
}
public class Tiger : Animal
{
// How do I set "_name" here?
}
I want to hard-code the _name value in the Tiger class. However, I don't want to force other classes to set the _name value. How do I do that in C#?
Just add a constructor:
public Tiger()
{
_name = "Tony"; // they're great!
}

StackOverFlowException in file with two classes

The following code generates StackOverFlowException. The question is why? It looks legit to me...
using System;
namespace learning
{
public class TestClass
{
private String name;
public String Name
{
get => Name;
set => name = value;
}
}
class Program
{
static void Main(string[] args)
{
TestClass e = new TestClass();
Console.WriteLine(e.Name);
}
}
}
I tried removing the namespace learning {...} but it didn't change anything.
Your property is returning itself:
public String Name
{
get => Name;
set => name = value;
}
Instead, it should return the field name (case sensitive):
public String Name
{
get => name;
set => name = value;
}
You are making a recursive call to the property Name, target the field instead i.e name
public String Name
{
get => name;
This is a perfect reason why i like to underscore my fields names _name, The other being so i don't have to use this.name in methods or constructor

GetSet in C# not being parsed

Relatively minor question about something I am missing here,
I am attempting to do a simple GetSet in C# to get the hang of the syntax but appear to have missed something as all that is printed is GetSet.Role and not the actual attributes being assigned.
Have I just worded something wrong? Apologies for the minor question but any help is appreciated.
namespace GetSet
{
class Program
{
static void Main(string[] args)
{
Role Mage = new Role("Staff", "Robes", "Magic affinity");
Role Warrior = new Role("Sword", "Platebody", "Strength");
Role Rogue = new Role("Needle", "Leather", "Cunning");
Console.WriteLine(Mage);
Console.WriteLine(Warrior);
Console.WriteLine(Rogue);
//stop the program from closing
Console.ReadLine();
}
}
}
and the following is my class:
namespace GetSet
{
class Role
{
//private variables
private string weapon;
private string armour;
private string passive;
//public structs
public Role(string aWeapon, string aArmour, string aPassive)
{
weapon = aWeapon;
armour = aArmour;
passive = aPassive;
}
//Getters and Setters for above private variables
public string Weapon
{
get { return weapon; }
set { weapon = value;}
}
public string Armour
{
get { return armour; }
set { armour = value;}
}
public string Passive
{
get { return passive; }
set { passive = value;}
}
}
}
Add a ToString() to your Role class and set it return whatever you want:
public override string ToString()
{
return $"Weapon: {weapon}, Armor: {armor}, Passive: {passive}";
}
You need to override the ToString method on the GetSet class.
Something like:
public override string ToString()
{
return $"{weapon}/{armour}/{passive}";
}
Update
You can simplyfy your Role class.
internal class Role
{
public Role(string weapon, string armour, string passive)
{
Weapon = weapon;
Armour = armour;
Passive = passive;
}
public string Weapon { get; }
public string Armour { get; }
public string Passive { get; }
public override string ToString()
{
return $"{Weapon}/{Armour}/{Passive}";
}
}
Re: vasily.sib's comment.
If you need to change the properties after object creation then simply change
public string Passive { get; }
to
public string Passive { get; set; }
As other answers lacks of getters/setters syntax examples, I will post my.
namespace GetSet
{
public class Role
{
// private backing field
private string _weapon;
// properties can have getters and setters, that contains some logic
public string Weapon
{
get { return _weapon; }
set { if (_weapon != vale) _weapon = value; }
}
// there is an auto-getters/setters
// in this case, backing field is handled by .Net CLR
public string Armour { get; set; }
// getters and setters may have different access level
// also, note property initializer '= "John";' - this will set property value
// to "John" right before constructor invocation
public string Name { get; private set; } = "John";
// properties also can be readonly, so they can be setted only in constructors
public string Passive { get; }
// public constructor
public Role(string passive)
{
Passive = passive;
}
public void ChangeName(string newName)
{
Name = newName; // setting property through private setter
}
// I believe, that this method shouldn't be used to represent object as string
// At least, I think, you should never relay on it's return value, BUT it ups to you
public overide string ToString() => Name;
}
}
Also, as you can see, I'm not setting publicly available properties (properties with public setters, Weapon and Armour) in consturctors, because I can initialize them along with constructing Role object, like this:
var mage = new Role("Magic affinity") { Weapon = "Staff", Armor = "Robes" };
mage.ChangeName("John, Doe");
As said before, I beleive that it is not relay on object itself, how it will look in string. I thinking so, because if you for some reasons need to represent same object as different strings in different places of your code - this will cause troubles. So instead of this:
// this will call .ToString() method
Console.WriteLine(mage);
// output: John, Doe
I suggest this:
// represent object as you need
Console.WriteLine($"{mage.Name} - walks in {mage.Armour}, beats with {mage.Weapon}");
// output: John, Doe - walks in Robes, beats with Staff

how to use c# snippet prop?

Just got to know about C# snippet. But i am unable to use them in my code.
Help me out please, I am messed up with get set and how they work.
Here is my test class named "myclass"
namespace WindowsFormsApplication1
{
class myclass
{
public string getmessage(string givenName)
{
return "HB "+givenName;
}
private string bmessage;
public string MyProperty
{
get { return bmessage; }
set { bmessage = value; }
}
}
}
In button code from my form. I am unable to use these get set.
It ll be great if someone clears that how can i use these get set.
Moreover what is "MyProperty" here? I know it is not a method. What is its purpose? Thanks
Snippets itself are not executable statements. But are short-cuts that help you in writing executable statements.
For e.g.
If we write prop and press enter, it will give you a auto-generated property. You just have to change Datatype and Property Name.
Similarly propfull will give a property with get and set parts.
In your case MyProperty is the Property Name and string is the DataType. bmessage is the backing field for your property.
The properties of a class are set and retrieved by using set/get methods. Basically these are also methods.
namespace BusinessObjects
{
public class class_BusinessObjects
{
int StusentId;
string StudentName;
public class_BusinessObjects ()
{
StusentId = 0;
StudentName = string.Empty;
}
public int StusentId
{
get
{
return Id;
}
set
{
Id = value;
}
}
public string StudentName
{
get
{
return Name;
}
set
{
Name = value;
}
}
}
}
using BusinessObjects;
namespace MyModel
{
public class A
{
public class_BusinessObjects Dispaly(int id, string name)
{
class_BusinessObjects obj = new class_BusinessObjects();
obj.StusentId = id;
obj.StudentName = name;
return obj;
}
}
}

How can I have my DebuggerTypeProxy target class inherit from base proxies?

Question:
I'm looking for a way to simplify the construction of debugger type proxies for inherited classes. So, when debugging a class that inherits from another, I should see the properties of both side-by-side: the base properties of the base class, plus the new properties of the parent class.
Here's what I've tried so far:
NewA's type proxy inherits from that of A. Properties don't show side-by-side; base properties are umbrella'd [sic] under Base. *****
Including an A property in NewA that just casts the current NewA to A, with [DebuggerBrowsable(RootHidden)]: Visual Studio hangs :(
I know that I could just add properties for the base class into NewA's proxy, but I'm trying to avoid this. It's too much work for classes with many properties.
Explanation:
I'm using the DebuggerTypeProxy attribute on some of my classes so I can control how the class looks when browsed during debugging. For example:
public class A {
private String _someField;
public String SomeField {
get {return _someField;}
}
}
By default, the tooltip debugging info shows as:
... so I use a DebuggerTypeProxy to hide the backing field:
[DebuggerTypeProxy(typeof(AProxy))]
public class A {
// ...
internal class AProxy {
A _a;
AProxy (A a){
_a = a;
}
public String SomeField {
get {return _a.SomeField;}
}
}
}
... all is right with the world:
Now, I create a class that inherits from A.
public class NewA : A {
private String _anotherField;
public String AnotherField {
get {return _anotherField;}
}
}
Unfortunately, when debugging this class, Visual Studio uses the base type proxy (from A). This means we can see the base SomeField property, but our new AnotherField property is hidden (unless you expand Raw View, of course):
Removing the type proxy from base A results in AnotherField showing, but not SomeField.
* Failed attempt #1
/// <summary>
/// The base class
/// </summary>
[DebuggerTypeProxy(typeof(AProxy))]
public class A {
private String _someField;
public String SomeField {
get { return _someField; }
}
protected class AProxy {
A _a;
protected AProxy(A a) {
_a = a;
}
String SomeField {
get { return _a.SomeField; }
}
}
}
/// <summary>
/// Parent class
/// </summary>
[DebuggerTypeProxy(typeof(NewAProxy))]
public class NewA : A {
private String _anotherField;
public String AnotherField {
get { return _anotherField; }
}
// Inherit base type proxy, in an effort to display base properties
// side-by-side with AnotherField: Doesn't work.
protected class NewAProxy : A.AProxy {
NewA _newA;
protected NewAProxy(NewA newA)
: base(newA) {
_newA = newA;
}
public String AnotherField {
get { return _newA.AnotherField; }
}
}
}
Result:
Still doesn't work. Base properties are not placed side-by-side with the new properties.
After hours of searching and tinkering, I found the solution - and a beautiful one at that - from Jared Par's blog. He creates a type proxy that uses reflection to condense all the members into one list. Some additional DebuggerDisplay magic makes it so you don't even notice.
// http://blogs.msdn.com/b/jaredpar/archive/2010/02/19/flattening-class-hierarchies-when-debugging-c.aspx
// by Jared Par
internal sealed class FlattenHierarchyProxy {
[DebuggerDisplay("{Value}", Name = "{Name,nq}", Type = "{Type.ToString(),nq}")]
internal struct Member {
internal string Name;
internal object Value;
internal Type Type;
internal Member(string name, object value, Type type) {
Name = name;
Value = value;
Type = type;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly object _target;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Member[] _memberList;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
internal Member[] Items {
get {
if (_memberList == null) {
_memberList = BuildMemberList().ToArray();
}
return _memberList;
}
}
public FlattenHierarchyProxy(object target) {
_target = target;
}
private List<Member> BuildMemberList() {
var list = new List<Member>();
if ( _target == null ) {
return list;
}
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var type = _target.GetType();
foreach (var field in type.GetFields(flags)) {
var value = field.GetValue(_target);
list.Add(new Member(field.Name, value, field.FieldType));
}
foreach (var prop in type.GetProperties(flags)) {
object value = null;
try {
value = prop.GetValue(_target, null);
}
catch (Exception ex) {
value = ex;
}
list.Add(new Member(prop.Name, value, prop.PropertyType));
}
return list;
}
}
Modifications
I made three little modifications to the class to make it more usable for me.
First, I wanted the members sorted by name. To do this, change the last line to:
return list.OrderBy(m => m.Name).ToList();
Second, in the Member struct, I added some attributes so that only the value would show when you expand a reference class:
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal string Name;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
internal object Value;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal Type Type;
Third, the default flags BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance mean that even members marked [DebuggerBrowsable(DebuggerBrowsableState.Never)] will still be shown. To prevent this from happening, after this line:
foreach (var field in type.GetFields(flags)) {
add this:
// Respect DebuggerBrowsableAttributes
var debuggerBrowsableAtts = field.GetCustomAttributes(typeof(DebuggerBrowsableAttribute), true);
if (debuggerBrowsableAtts.Count() == 1) {
var att = debuggerBrowsableAtts[0] as DebuggerBrowsableAttribute;
if (att.State == DebuggerBrowsableState.Never) {
continue;
}
}
Now the DebuggerBrowsable(DebuggerBrowsableState.Never) will be respected for fields. You can also add that code the foreach loop that handles properties, to have it respected for properties as well.

Categories

Resources