I have little problem using inheritance. I can neither change the value of first and second in class C nor first in class B when they are protected. If these variables are public everything works fine, but in this case what's the point of using protected?
class A
{
protected int first { get; set; }
}
class B : A
{
protected int second { get; set; }
public Show()
{
A a = new A();
a.first = 5;
}
}
class C : B
{
private int third { get; set; }
static void Main()
{
B b = new B();
b.first = 1;
b.second = 2;
}
}
The main problem is simply caused by you putting your program's entry point inside the class you want to test. Because Main() is static, you can't access C's (inherited) instance members.
So separate it:
class Program
{
static void Main()
{
C c = new C();
c.Test();
}
}
Your class C inherits from B, so C can access B's protected members like so:
class C : B
{
private int third { get; set; }
public void Test()
{
first = 1; // from A
second = 2; // from B
third = 3; // from C
}
}
By newing a B inside C, there's no relation between those instances of B and C, so all you can access there are B's public and internal members.
You're allowed to access the protected members when you're dealing with instances of your own class:
class B :A
{
protected int second { get; set; }
public show() {
this.first = 5; //This is valid
}
}
If you were allowed arbitrary access to your base class' protected members, on any instance of the base class, this would be allowed:
class DDefinitelyNotB : A
{
}
class B :A
{
protected int second { get; set; }
public show() {
A a = new DDefinitelyNotB ();
a.first = 5;
}
}
And that could be bad for DDefinitelyNotB, which isn't expecting other classes that just happen to derive from A to be able to interfere with the protected members it's inherited from A.
Related
Say I have the following
public class A{
public string foo {get;set;}
public string bar {get;set;}
public int baz {get;set;}
}
public class B:A
{
public string wuz {get;set;}
}
public class C:A
{
public int yuh {get;set;}
}
If I then make an instance of B
var b = new B(){wuz="wow",foo="hello",bar="wordl",baz=18};
and later on I want to use those values of B in C, then I have to manually write
c = new C(){yuh=20, foo = b.foo, bar = b.bar, baz=b.baz};
isn't there a way to make c take the already instantiated values from B in a dynamic way, and parse them onto C? In this example it is easy to to, but say I have 500 properties then it's not feasible
(I'm fairly new to .NET thus there might be a typo/syntax error in the codeexample above, but I think the problem should be rather clear)
You can add a constructor to C that takes an instance of A (or if you really want to do that B). Would look something like this:
public class C:A
{
public C() {}
public C(A other)
{
this.foo = other.foo;
...
}
public int yuh {get;set;}
}
If you also want the same capability in B, you might want to add this kind of constructor to A, and call it from C:
public class A{
public A(){}
public A(A other)
{
this.foo = other.foo;
...
}
public string foo {get;set;}
public string bar {get;set;}
public int baz {get;set;}
}
public class C:A
{
public C(){}
public C(A other) : base(other) {}
public int yuh {get;set;}
}
In either case you can now create a new instance of Clike this:
c = new C(b){ yuh = 20};
Yes you can. You need to write method that will take B instance and sets all properties with reflection.
public C CreateCFromB(B bInstance)
{
var cInstance = new C();
foreach (var property in typeof(B).GetProperties())
{
var propertyValue = property.GetValue(bInstance, null);
property.SetValue(cInstance, propertyValue);
}
return cInstance;
}
You can take more generalized approach with generic types.
public TWhat CreateFrom<TFrom, TWhat>(TFrom tFromInstance)
where TWhat : TFrom, new()
{
var tWhatInstance = new TWhat();
foreach (var property in typeof(TFrom).GetProperties())
{
var propertyValue = property.GetValue(tFromInstance, null);
property.SetValue(tWhatInstance, propertyValue);
}
return tWhatInstance;
}
I have a question about overriding properties in C#. There already is a similar question here, but the answers are not satisfying for me. Let's say I have these classes:
class A
{
public int Prop { get; }
}
class B : A
{
public int Prop { get; set; }
}
Now as you can see I want to add a setter to the property Prop in a subclass. I came up with two solutions. The first one is making the property virtual and overriding it in class B like this:
class A
{
public virtual int Prop { get; }
}
class B : A
{
public override int Prop { get; set; }
}
But unfortunately the compiler doesn't allow me to do this. My second idea was to use a 'new' keyword:
class A
{
public virtual int Prop { get; }
}
class B : A
{
public new int Prop { get; set; }
}
Now everything seemingly works, but it's not a satisfying solution for me because of one detail. Let's consider for instance this piece of code:
B b = new B();
b.Prop = 5;
A a = b;
Console.WriteLine(a.Prop);
You probably know that I get 0 here in my output, but I want to get 5. Is there any way to solve this problem?
You could try to explicitly implement property's setter. This requires an interface:
public interface IPropSet
{
int Prop { set; }
}
class A
{
protected int prop;
public int Prop => prop;
}
class B : A, IPropSet
{
int IPropSet.Prop
{
set => prop = value;
}
}
But unfortunately this property cannot be set without casting to IPropSet:
((IPropSet)new B()).Prop = 1;
Another option is to use a backing field and to create the Prop as new in B as follows:
class A
{
protected int prop;
public int Prop => prop;
}
class B : A
{
public new int Prop
{
get => prop;
set => prop = value;
}
}
Sample usage:
var b = new B { Prop = 1 };
Console.WriteLine(((A)b).Prop); // 1
On Console.WriteLine(a.Prop); you reference to A.Prop, new in B class for Prop is for redefining.
When used as a declaration modifier, the new keyword explicitly hides a member that is inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base class version. This assumes that the base class version of the member is visible, as it would already be hidden if it were marked as private or, in some cases, internal. Although you can hide public or protected members without using the new modifier, you get a compiler warning. If you use new to explicitly hide a member, it suppresses this warning. Microsoft docs
but you can use,
if (a is B bb)
{
Console.WriteLine(bb.Prop);
}
Or use this pattern
class A
{
public virtual int Prop { get; protected set; }
}
class B : A
{
public void SetProp(int prop) => Prop = prop;
}
B b = new B();
b.SetProp(5);
A a = b;
Console.WriteLine(a.Prop);
Property's set-ter in class A should be protected. You will still be able to override it and it still won't be accessible outside class A and its children.
Edit: I've read your question once again and tested my edited answer in Visual Studio (I haven't had a chance to do it the first time).
As I understand, besides overriding the property, you want to be able to set property's value on a subclass, from outside the class, but not setting it on the base class.
You could try something like this:
using System;
namespace PropertyInheritance
{
public class Program
{
static void Main(string[] args)
{
A a1 = new A();
B b1 = new B();
a1.Prop = 1;
b1.Prop = 2;
Console.WriteLine($"a1.Prop = {a1.Prop}");
Console.WriteLine($"b1.Prop = {b1.Prop}");
Console.WriteLine($"a1.GetPropField() = {a1.GetPropField()}");
Console.WriteLine($"b1.GetPropField() = {b1.GetPropField()}");
B b2 = new B();
b2.Prop = 5;
A a2 = b2;
Console.WriteLine($"a2.Prop = {a2.Prop}");
Console.WriteLine($"a2.GetPropField() = {a2.GetPropField()}");
Console.ReadLine();
}
}
public class A
{
protected int prop;
public virtual int Prop {
get { return prop; }
set { }
}
// test method - to check field's value
public int GetPropField() => prop;
}
public class B : A
{
public override int Prop
{
get { return prop; }
set { prop = value; }
}
}
}
Here is the output:
I suppose everything is clear, but if not, please feel free to ask. Maybe I still didn't understand the question, or even made some mistake in my answer.
A is not a subclass of B, this is not how inheritance works. I don't understand why do you want to do this, I think you are mistaken the complete concept of inheritance
In the case you proposes:
class A
{
public int Prop { get; }
}
class B : A
{
public int Prop { get; set; }
}
they are the same property. If you do a:
class A
{
public int Prop { get; }
}
class B : A
{
public int AnotherProp { get; set; }
}
you can set:
B instance = new B();
B.Prop = 5;
If what you want to do is having a property in a subclass with the same name (not recommended) you can do this, without working with inheritance:
internal class A
{
internal int Prop { get; }
}
internal class B
{
internal A MySubClass { get; set; }
}
B instanceB = new B();
A instanceA = new A();
instanceA.Prop = 5;
B.MySubClass = instanceA;
or you can play with that, without copy it directly. Is just an example to show you the difference between class as property and inheritance
How do I get the value of a static property from an instance of a class? see example below...
abstract class A {
public static double Foo {get; protected set;}
}
class B : A {
static B(){
Foo = 1;
}
}
class C : A {
static C(){
Food = 2;
}
}
class Test {
A test = new B();
//How do I get test.Foo ??
}
Static members (fields, properties, methods, etc.) are accessed via class name.
var x = A.Foo;
I think you are getting statics wrong.
Did you mean something like this?
abstract class A {
public double Foo {get; protected set;}
}
class B : A {
public B(){
Foo = 1;
}
}
class C : A {
public C(){
Foo = 2;
}
}
class Test {
A test = new B();
var foo = test.Foo;
}
This's Class A
Class A
{
public string uname { get; set; }
public string fname { get; set; }
}
I set values by Class B
Class B
{
private void Main(){
A aGetSet = new A();
aGetSet.uname = "James";
aGetSet.fname = "Blunt";
}
}
But when I get values in Class C, it's always return null
Class C
{
private void Main() {
A aGetSet = new A();
string username = aGetSet.uname;
string fistname = aGetSet.fname;
}
}
Does anyone has solution for this problem?
The aGetSet declared in B is an object of A. The aGetSet declared in C is another object of A. They are completely independent of each other. Changing the values of one of the objects does not affect the values of the other.
To fix this problem, you need to make it so that you are accessing the same instance in B and C.
There are lots of ways to do this. I will show you how to use the singleton pattern.
class A
{
public string uname { get; set; }
public string fname { get; set; }
private A() {} // mark this private so that no other instances of A can be created
public static readonly A Instance = new A();
}
class B
{
public void Main(){
// here we are setting A.Instance, which is the only instance there is
A.Instance.uname = "James";
A.Instance.fname = "Blunt";
}
}
class C
{
public void Main() {
B b = new B();
b.Main();
string username = A.Instance.uname;
string fistname = A.Instance.fname;
}
}
Now you just need to call C.Main to make this work!
Your have 2 different objects in 2 classes. When you are using '= new A() ' it creates new instance.
The reason why you are getting null here:
string username = aGetSet.uname;
is default value for string type (as any reference type) is null.
To pass 'the same' object from class B into class C Main method change method in class C to public Main(ref A obj). That will not create a copy and use the same instance.
Call from class B:
A aObj = new A();
aGetSet.uname = "James";
aGetSet.fname = "Blunt";
C c = new C();
c.Main(ref aObj);
Creating a class with property a1
class A
{
public int a1 { get; set; }
}
Creating object for Class A in B and assigning value to it
class B
{
A a=new A();
a.a1=45;
}
How to get the the assigned value in different class.
class C
{
//How to access the 45 value from the class B instance variable here
//without using static keyword.
}
you could try
class A
{
public int a1 { get; set; }
}
class B
{
public A a = new A();
public B()
{
a.a1 = 45; //you need to put that in a method..
}
}
class C
{
B b = new B(); // instance of B in C
int aValue = b.a.a1; // access b's instance of A
}
better solution:
class A
{
public int a1 { get; set; }
}
class B
{
A a = new A();
public int A_Value
{
get { return a.a1; }
set { a.a1 = value; }
}
}
class C
{
B b = new B(); // instance of B in C
public C()
{
b.A_Value = 45;
}
}
Accept either an A or B as a parameter either in the method or constructor. In the case below, A and B are interchangeable.
public class C
{
A _a;
public C(A a)
{
_a = a;
}
void Do() // Using constructor parameter.
{
Console.WriteLine(_a.a1); // Should print 45, so long as your other code has already ran.
}
void Do(B b) // Using method parameter.
{
Console.WriteLine(b.A.a1); // will write 45
}
}
With respect, these answers just seem to be muddying the water. At risk of feeding a troll here, because it appears this question has no practical application, I'll submit my suggestion. Aside from some basic conventions, I'd added public constructors for each class, applied a public getter for the instance of A stored in B, and then provided a method on C that returns the "A1" property from the instance of A within the instance of B. Having written that last sentence punctuates how convoluted this task has been.
public class A
{
public A() { }
public int A1 { get; set; }
}
public class B
{
public B()
{
this._a = new A() { A1 = 42 };
}
private A _a;
public A A
{
get { return _a; }
}
}
public class C
{
public C() { }
public int GetA1FromA()
{
return new B().A.A1;
}
}