I've been baffled by a behavior of new keyword in C#, as it doesn't seem to completely override its parent value, here's an example:
public static void Main(string[] args)
{
A test = new B();
Console.WriteLine(test.s);
}
public class A {
public string s = "A";
}
public class B : A{
public new string s = "B";
}
Now here I expected "B" to be printed, but instead, I got "A"
How can I always call the new property, whatever class is renewing it, instead of the original one?
The new keyword basically hides the member under a new member of the same name. However, this new member with the same name only exists on the subclass B and not on the base class A. So you wouldn't observe that test.s contains "B" unless you casted test to B first.
public static void Main(string[] args)
{
A test = new B();
Console.WriteLine(test.s); // A
B test2 = test as B;
Console.WriteLine(test2.s); // B
}
public class A
{
public string s = "A";
}
public class B : A
{
public new string s = "B";
}
If you want the member to be replaced, then you have to use the override keyword. However, you cannot override fields, only methods and properties. Try this:
public class A
{
protected virtual string s { get => "A"; }
}
public class B : A
{
protected override string s { get => "B"; }
}
public static void Main(string[] args)
{
A test = new B();
Console.WriteLine(test.s); // will print B
}
The virtual keyword on A.s indicates that that property can be overridden.
Julo's comment correctly points out that it is bad form to try to modify fields from subclasses anyway. Generally, class fields should always be private.
For methods and properties, you can do this by replacing new with override. override actually overrides the method, while new only hides it.
The same goes for fields, but you can't use override with fields.
But if you look closely, what you want here is to override the initial value of s. In both classes, s can be changed later on.
To change the initial value, just write a constructor:
public B() {
s = "B";
}
As it's already been pointed out, the new keyword is only going to hide the value, not override it. To do that, you'd need to use the override keyword, which can't be used on fields, but it can be used on properties, like this:
public static Main(string[] args)
{
A test = new B();
Console.WriteLine(test.S); // Prints "B"
}
public class A
{
protected string s;
public virtual string S { get => "A"; set => s = value; }
}
public class B : A
{
public override string S { get => "B"; set => s = value; }
}
This is probably the closest to what you expected to happen, but we have to introduce the backing field to be able to change the value of S. If you don't plan on doing so, you can just use public virtual string S => "A"; and making it a readonly.
However, this probably isn't the intended use of overriding properties. It's most likely there to do something different in the get or set functions like this:
public class A
{
public virtual string S
{
// Do Something
}
}
public class B : A
{
public override string S
{
// Do something else
}
}
Since all you're doing is changing the values, it's probably better to just do it in the constructor.
public class A
{
public string S { get; set; } = "A";
}
public class B : A
{
public B() => S = "B";
}
The downside of using the constructor is that, if you're changing the value for all the child classes, you're not gonna be able to quickly tell what the value is without opening up the constructor, which might make it harder to find. So, all in all, it's gonna come down to personal preference on which approach you use.
Related
Base Class
class TestBase
{
protected int a;
protected int b;
public TestBase(int i)
{
a = i;
}
protected TestBase()
{
}
public void Update(int i)
{
a = i;
TestChild child = new TestChild();
child.Update("Hello World ");
}
Child Class
class TestChild:TestBase
{
private string msg;
public void Update (string s)
{
msg = s+ a.ToString();
Console.WriteLine("msg=" + msg);
}
}
Calling
private void btnTest_Click(object sender, EventArgs e)
{
TestBase t = new TestBase(1);
t.Update(100);
}
Result
Hello World 0
Problem
I was hoping to get Hello World 100. Obviously the child class did not access base class variable int a. how can I do that?
First of all, it's not clear what you're trying to accomplish.
There are many problems with this code. First, you should not be creating an instance of TestChild inside a TestBase class method. If you create an instance of TestBase inside btnTest_Click, then there is no way you'll be able to access any of TestChild's methods or data (except that you are creating an instance of TestChild inside TestBase which is bad practice).
The purpose of inheritance is usually to extend the data/methods for a base class, not to use an inherited class inside a base class. Also, with a set of inherited classes, you can achieve polymorphism which is another core principle of Object Oriented Programming. You should get a better understanding of these principles and then the code will start making more sense.
The object you created in TestBtn_Click has nothing to do with the object you created in TestBase.Update. They are two different objects so each have their own a field with different values.
To produce the output you expect, you need to set child.a to this.a in Update:
public void Update(int i)
{
a = i;
TestChild child = new TestChild();
child.a = this.a;
child.Update("Hello World ");
}
The important thing to understand here is that inheritance does not affect objects. Inheritance only affects classes. The base class members will also be present in the subclass. That's it. Even though objA's type inherits from objB, they are unrelated unless they are the same object.
public void Update(int i)
{
a = i;
TestChild child = new TestChild();
child.Update("Hello World ");
}
This is where you are assigning value to variable a, and later you instantiated another instance of TestChild class which is different.
After this instantiation you have to assign the value like
TestChild child = new TestChild();
child.a = i;
child.Update("Hello World ");
Then you shall get your desired result
The child object inside your TestBase doesn't know where is he placed. It doesn't know it is inside of a class.
When you create the child you also create a totally different TestBase object which is not the same as what contains the child. When you create that object a will be initialized to a default value which is 0 in this case.
If you would like to carry the value of a to an other object you should give it to it. For example through the constructor.
Call like this:
TestChild child = new TestChild(a);
Make a constructor like this:
public TestChild(int x) : base(x){}
Unfortunately your concept bleeding from everywhere so it will not work in this form. I recommend to study inheritance more.
This is how to use inheritance:
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog("Dalmata", "Fuffy", 7);
}
}
class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public Animal(string name, int age)
{
Name = name;
Age = age;
}
}
class Dog : Animal
{
public string Race { get; set; }
public Dog(string race, string name, int age) : base(name, age)
{
Race = race;
}
}
This way, you will acess Name and Age too, even if they are declared in Animal.
you should call your base class this way
class BaseClass
{
int a;
int b;
protected BaseClass()
{ }
protected BaseClass(int i)
{
a = i;
}
protected void Update(int i)
{
a = i;
Console.Write("Hello World ");
}
}
class TestChild : BaseClass
{
public TestChild(int i) : base(i) //send your constuctor to your base class
{ }
public TestChild()
{ }
public void Update(int i)
{
base.Update(i);
Console.Write(i.ToString());
}
}
private void btnTest_Click(object sender, EventArgs e)
{
TestChild t = new TestChild(); // create instance as your child
t.Update(100);
}
create your object as your child class then call your method and let it call your base class
also if wanna access a or b in base class from your child
public int a;
public it so you can access it from instance you created
protected will allow only inside child class to access to it
If you'd like to get the expected result, put a static modifier front of a and/or b variables, like this:
static protected int a;
static protected int b;
After this, if you push that button it will write out:
msg=Hello World 100
I have read an article regarding the new keyword. It says it is used to hide methods. This is example they give:
using System;
namespace ConsoleApplication3
{
class SampleA
{
public void Show()
{
Console.WriteLine("Sample A Test Method");
}
}
class SampleB:SampleA
{
public void Show()
{
Console.WriteLine("Sample B Test Method");
}
}
class Program
{
static void Main(string[] args)
{
SampleA a = new SampleA();
SampleB b = new SampleB();
a.Show();
b.Show();
a = new SampleB();
a.Show();
Console.ReadLine();
}
}
}
Output:
Sample A Test Method
Sample B Test Method
Sample A Test Method
So my question isn't the new keyword used to instantiated an object? and its used to allocate memory for new created objects? Then how can method hiding be done using it? And is above example correct?
new is used for 3 different things. You could say there are 3 different keywords with the same name.
It's an operator, used to invoke constructors. Example: new object();
It's a modifier, used to hide an inherited member from a base class member. Example:
class Base {
public void MyMethod() {
//Do stuff
}
}
class Derived : Base {
public new void MyMethod() {
//Do other stuff
}
}
It's a generic type constraint, used to indicate that a generic type parameter has a parameterless constructor. Example:
class MyGenericClass<T> : where T : new() { ... }
Source: new
Isn't the new keyword used to instantiated an object?
Yes it is. Among other things.
then how can method hiding done using it?
The new keyword in the context of method and property definitions has another meaning than the new keyword used to instantiate objects. The new keyword in that context tells that there is a new start of the inheritance tree of that particular method or property. That's all.
Then how can method hiding be done using it? And is above example
correct?
Programming language syntax, grammar and semantics are just an arbitrary set of conventions and specifications. That is, C# can invent one, two or dozen of usages of a given keyword like new.
When new is used during a class member declaration, it means that you're re-using an identifier:
public class A
{
public string Text { get; set; }
}
public class B : A
{
new public int Text { get; set; }
}
As you can check in above code sample, B also implements a Text property, but since derives from A which has also defined a Text property, there's a naming collision.
The so-called new keyword can be used to re-use Text identifier and being able to implement another property Text which may behave absolutely different than the one implemented in the base class. See that Text on B is of type int!
The most important point here is that re-using identifiers isn't the same as using polymorphism, where a class method or property override must match base class' member signature:
public class A
{
public virtual string Text { get; set; }
}
public class B : A
{
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
}
Also, re-used identifiers are dangerous:
public class A
{
public string Text { get; set; }
}
public class B : A
{
new public int Text { get; set; }
}
B b = new B();
b.Text = 4;
// Upcast B to A
A a = b;
a.Text = "Bye bye";
Console.WriteLine(a.Text); // Output: Bye bye
Console.WriteLine(b.Text); // Output: 4
See the output of Text. Since re-using identifiers isn't polymorphism, and in above case both are completely different properties, there's an A.Text and B.Text that can be set separately.
To hide an inherited member, declare it in the derived class by using the same member name, and modify it with the new keyword. For example:
public class BaseC
{
public static int x = 55;
public static int y = 22;
}
public class DerivedC : BaseC
{
// Hide field 'x'.
new public static int x = 100;
static void Main()
{
// Display the new value of x:
Console.WriteLine(x);
// Display the hidden value of x:
Console.WriteLine(BaseC.x);
// Display the unhidden member y:
Console.WriteLine(y);
}
}
/*
Output:
100
55
22
*/
You can read more in here
Say I have code out there like this:
public class Base // I cannot change this class
{
public string Something { get; private set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
// How can I wrap the PreSets here so that they return SubClass objects?
// Something like this:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
}
}
}
What makes this complicated is the Something property. It has a private setter. So I can't set it in the subclass. The only way it can be set is is via the preset properties.
Is there a way to wrap the StaticPreSet property in my SubClass so that it will return an object of type SubClass?
// I cannot change this base class.
Given that you can't change the base class, there is no way to cause it to change behavior (ie: return a different class at runtime).
If you could influence the design of the base class static methods, you could redesign it in a way to be flexible enough to provide this functionality. However, without changing it, this won't work.
Edit in response to edit:
You could create a new static method that does what you are showing, like so:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
Base baseInstance = Base.StaticPreSet;
SubClass sc = new SubClass(baseInstance); // Create a new instance from your base class
return sc;
}
}
However, this provides a completely new, unrelated property - you'd have to access it via SubClass.MyWrappedPreset, not the Base class.
Static fields in a class "have nothing to do with it".
Basically, except access to private static fields, id doesn't matter in which class you put them - they behave the same.
If you inherit a class, and you declare another static field with the same name of a static field on the base class, you will simply 'hide' it. Example for you:
using System;
public class Base // I cannot change this class
{
public string Something { get; set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
public static SubClass StaticPreSet2
{
get { return new SubClass { Something = "inherited", Otherthing=""}; }
}
}
public class Test
{
public static void Main()
{
Console.WriteLine(SubClass.StaticPreSet2.Something);
}
}
Will write "inherited".
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).
I've been given a .NET project to maintain. I was just browsing through the code and I noticed this on a property declaration:
public new string navUrl
{
get
{
return ...;
}
set
{
...
}
}
I was wondering what does the new modifier do to the property?
It hides the navUrl property of the base class. See new Modifier. As mentioned in that MSDN entry, you can access the "hidden" property with fully qualified names: BaseClass.navUrl. Abuse of either can result in massive confusion and possible insanity (i.e. broken code).
new is hiding the property.
It might be like this in your code:
class base1
{
public virtual string navUrl
{
get;
set;
}
}
class derived : base1
{
public new string navUrl
{
get;
set;
}
}
Here in the derived class, the navUrl property is hiding the base class property.
This is also documented here.
Code snippet from msdn.
public class BaseClass
{
public void DoWork() { }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork() { }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
DerivedClass B = new DerivedClass();
B.WorkProperty; // Calls the new property.
BaseClass A = (BaseClass)B;
A.WorkProperty; // Calls the old property.
Some times referred to as Shadowing or method hiding; The method called depends on the type of the reference at the point the call is made. This might help.
https://msdn.microsoft.com/en-us/library/435f1dw2.aspx
Look at the first example here, it gives a pretty good idea of how the new keyword can be used to mask base class variables