using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List list = new List();
list.Add(new A());
var list2 =
from p in list
select p as B;
Console.WriteLine(list2.First().myString);
Console.ReadLine();
}
}
class A
{
public string myString = "abc";
}
class B : A
{
}
}
How can I solve this?
Thanks
You can't do that; the list contains an instance of A, you can't cast A to B. You can only cast "upwards" in the inheritance chain, not downwards. So if you change places on A and B in your code, it works:
class Program
{
static void Main(string[] args)
{
List<B> list = new List<B>();
list.Add(new B());
var list2 =
from p in list
select p as A;
Console.WriteLine(list2.First().myString);
Console.ReadLine();
}
}
class A
{
public string myString = "abc";
}
class B : A { }
If you want to convert in the other direction, you need to write code for the conversion:
class Program
{
static void Main(string[] args)
{
List<A> list = new List<A>();
list.Add(new B());
var list2 = list.ConvertAll<B>(a => B.FromA(a));
Console.WriteLine(list2.First().myString);
Console.ReadLine();
}
}
class A
{
public string myString = "abc";
}
class B : A
{
public B() { }
public static B FromA(A fromInstance)
{
B result = new B();
result.myString = fromInstance.myString;
return result;
}
}
list2.First().myString will try to access myString on a null reference. The as operator returns null if you can't cast. And object-oriented design principles tell us that you can use a subclass in any place where you can also use its superclass but not the other way around. So you're filling your list with instances of A and try to cast them to B. But they simply aren't instances of B so that cast will always fail (and, since you're using as, return null).
Your program does "convert father class to son class", contrary to your question title. Anyway, that can't be done.
To clarify this:
Try changing class B to the following:
class B : A
{
public string MyStringB { get; set; }
}
If you were able to cast A to B, what would the myStringB value be since it was never defined on A?
Create a constructor in B class which takes an instance of A class.
You can create a copy constructor which takes an object of type A:
class B : A
{
public B(A copy) {
myString = copy.myString;
}
}
I'm not too familiar with LINQ, however, so I'm not sure how you'd get it to automatically use this.
Related
Casting does not make copies of objects. More concretely IEnumerable.Cast, according to this resource, which makes total sense. However for this app, find fiddle, reference equals is false if I change the log at the end from the Cast<BaseClass> to Cast<DerivedClass1>. Check logs at the main program.
are equal: True areEqualRef: True areEqualRef: False
Posting the code, just in case, omit it of you get my point playing around with the fiddle :)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp17
{
public class BaseClass {
string name = "I am base";
public Type type;
public enum Type {
a,b,c,d
}
public BaseClass(Type type) {
this.type = type;
}
}
public class DerivedClass1 : BaseClass
{
string name = "I am derivedA";
public DerivedClass1(): base(Type.a) {
}
}
public class DerivedClass2 : BaseClass
{
string name = "I am derivedB";
public DerivedClass2() : base(Type.b)
{
}
}
public class Foo
{
public Dictionary<BaseClass.Type, List<BaseClass>> dict = new Dictionary<BaseClass.Type, List<BaseClass>>();
public Foo() {
dict[BaseClass.Type.a] = new List<BaseClass>();
dict[BaseClass.Type.b] = new List<BaseClass>();
dict[BaseClass.Type.c] = new List<BaseClass>();
dict[BaseClass.Type.d] = new List<BaseClass>();
AddItem(new DerivedClass1());
AddItem(new DerivedClass1());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
}
public IEnumerable<T> GetEnumByType<T>(BaseClass.Type type) where T : BaseClass
{
if (dict.ContainsKey(type))
{
if (type == BaseClass.Type.a)
{
Console.WriteLine($"are equal: { object.ReferenceEquals(dict[type].Cast<T>(), dict[BaseClass.Type.a])}");
}
return dict[type].Cast<T>();
}
return null;
}
public void AddItem<T>(T item) where T : BaseClass
{
dict[item.type].Add(item);
}
}
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
IEnumerable myList = foo.GetEnumByType<BaseClass>(BaseClass.Type.a);
Console.WriteLine($"areEqualRef: {object.ReferenceEquals(foo.dict[BaseClass.Type.a].Cast<BaseClass>(), foo.dict[BaseClass.Type.a])}");
Console.ReadLine();
}
}
}
Update:
Updated the fiddle with both logs to avoid the need of copy/pasting
You need to notionally separate what is being compared here. When it says that Enumerable.Cast<T> doesn't make copies of objects, it is talking about the individual objects in the sequence. Not the sequence itself. In order to perform the necessary reshaping, the sequence returned from the Cast<T> method is a different wrapper/decorator instance over the original sequence.
Since you're using ReferenceEquals on the sequence, this will report false. However, if you were to compare each object from the sequences (pairwise in turn), you would find that those were the same objects.
I would like set a variable to any of it children's type. Much better explained with code.
If I have:
public class B : A {
public int bCounter;
}
public class C : A {
public int cCounter;
}
I would like to do:
A myVarible;
if (someCondition) {
A = new B();
A.bCounter++;
}
if (someOtherCondition) {
A = new C();
A.cCounter++;
}
Kind of setting the parent as a wildcard variable, not to set every possible children type.
Is this kind of shortcut or similar possible?
Since the variable myVariable is of type A, it is not possible to address it using derived type members. (A does not know about B members.) Depending on your scenario, there are multiple options.
If there is no control over A, or the business logic requires it, you may be required to redeclare the variable to get it to compile.
if (someCondition) {
var b = new B();
b.bCounter++;
myVariable = b;
}
if (someOtherCondition) {
var c = new B();
c.cCounter++;
myVariable = c;
}
If it makes sense to do so, you could generate a method on A to IncrementCounter():
abstract class A
{
abstract void IncrementCounter();
}
public class B : A {
public int bCounter;
override void IncrementCounter() => bCounter++;
}
public class C : A {
public int cCounter;
override void IncrementCounter() => cCounter++;
}
This in turn lets you simplify your business logic:
A myVariable;
if (someCondition) {
myVariable = new B();
}
if (someOtherCondition) {
myVariable = new C();
}
myVariable.IncrementCounter();
I am working with C# where I need to create a single method which can accept parameter as a class name.
like: -
Class A
{
public string name {get;set;}
}
Class B
{
public int age {get;set;}
}
Class C
{
public decimal salary {get;set;}
}
A function will call MethodABC based on some condition.
Function1(){
A obj = new A();
MethodaBC(obj);
}
Function2(){
B obj = new B();
MethodaBC(obj);
}
Function3(){
C obj = new C();
MethodaBC(obj);
}
Method definition is: -
Static MethodABC(....)
Within MethodABC, I need to do some operation based on which class object has been passed in MethodABC.
You can always use the activator class to help you.
Example:
Type type = typeof(MyClass);
MyClass instance = (MyClass)Activator.Create(type);
//method example
public void ClassGet(string MyClassName,string blabla)
{
object instance = Activator.Create(MyClassName);
}
// Call it like:
Gold g = new Gold();
g.ClassGet("MyClass", "blabla");
You can pass the class as object as well:
//method example
public void ClassGet(MyClass MyClassName,string blabla)
{
object instance = Activator.Create(MyClassName);
}
// Call it like:
Gold g = new Gold();
g.ClassGet(MyClass, "blabla");
I'm currently having trouble and I have no clue how to fix it.
I have 2 classes:
class A
{
public string MyParam { get; set; }
}
class B : A
{
public new string MyParam { get { return base.MyParam != null ? base.MyParam.Substring(1) : null; } }
}
When I try to access the B.MyParam it works when I have a the correct type, but in most of my methods I have a generic type
with :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public class A
{
public string MyParam { get; set; }
}
public class B : A
{
public new string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
public static void MyMethod<T>(T variable) where T : A
{
Console.WriteLine(variable.MyParam);//this print hello
Console.WriteLine((variable as B).MyParam);//this print ello (exactly what i want)
Console.WriteLine(typeof(T)); // this print ConsoleApplication1.Program+A
Console.WriteLine(variable.GetType()); // this print ConsoleApplication1.Program+B
// so i need something like that
Console.WriteLine((variable as variable.GetType()).MyParam); // this line is invalid
}
static void Main(string[] args)
{
A a = new B();
a.MyParam = "Hello";
Console.WriteLine(a.GetType());
MyMethod(a);
Console.ReadKey();
}
}
}
Is there a way to do it?
Thank you in advance.
EDIT: it seems that what i want is :
dynamic variable2 = Convert.ChangeType(variable, variable.GetType());
Console.WriteLine(variable2.MyParam);
Your code doesn´t make any sense. If A inherits from B you´ll need A to override the base-implementation for your property. So I´ll assume you should rethink your inheritance-chain.
You can use override for this. Thus when your variable-parameter is of your base-class (I renamed that to A) you´re calling the base-method, if it´s a derived instance (here B) you´re calling the override:
class A
{
public virtual string MyParam { get; }
}
class B : A // note here that B derives from A, not the other way round
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; },
set { ... }
}
}
EDIT: While new intrduces a new member which (accidentally) has the same name (and signature) as the base-member it effectivly hides the base-member. Thus you effectivly have two members. Your only way to indicate which member should be used is by casting your instance to the desired class from which you need the implementation. However this somehow breaks the purpose of generics as the generic member has to know the exact types that are possible for the type-parameter.
Anyway this seems like broken design to me, as you´re actually creating a new member which has another meaning. So you should also give it a new name.
Based on your generic method, I think all you need is an interface.
public interface IMyParam
{
string MyParam { get; set; }
}
Your classes.
class A : IMyParam
{
public virtual string MyParam { get; set; }
}
class B : A
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
And your method, won't need to be generic.
public void MyMethod(IMyParam variable)
{
// Your logic here, for example.
Console.WriteLine(variable.MyParam);
}
Calling your method.
A a = new A();
a.MyParam = "Hello";
B b = new B();
b.MyParam = "Hello";
A ab = new B();
ab.MyParam = "Hello";
MyMethod(a); // Prints Hello
MyMethod(b); // Prints ello
MyMethod(ab); // Prints ello
Let's say I have three classes A, B and C as below, A and B have property Pro1 and Pro2 with Type C:
class A
{
public C Pro1 {get; set; }
}
class B
{
public C Pro2 { get; set; }
}
public class C
{
public void Do()
{
//How to get Type of object to reference to current object C
//Example: Either type A or B
}
}
In the method Do of class C I want to get which current parent object to reference to current object C (via Pro1 and Pro2). In this sample either A or B, but in general, it could be very dynamic:
var a = new A() { Pro1 = new C() };
a.Pro1.Do(); //will get Type A in Do
var b = new B() { Pro2 = new C() };
b.Pro2.Do(); //with get Type B in Do
Which approach I can achieve this?
You could pass the "parent" object as a parameter to the C constructor:
public class C
{
private readonly object _parent;
public C(object parent)
{
_parent;
}
public void Do()
{
Type type = _parent != null ? _parent.GetType() : null;
// Do something with type...
}
}
var a = new A() { Pro1 = new C() };
a.Pro1.Do(); //will get Type A in Do
var b = new B() { Pro2 = new C() };
b.Pro2.Do(); //with get Type B in Do
By this, you already know which object is making the call (a or b); what you are doing may not make sense then. If so, you can always resolve this with simple inheritance
C a=new A();
C b=new B();
and the ctors A or B can be inserted an identity of the caller.
Thomas Levesque has given one way of adding more info to C to achive this. If it is the type rather than the particular instance you want to store in C, you could make C generic, as in:
class A
{
public C<A> Pro1 { get; set; }
}
class B
{
public C<B> Pro2 { get; set; }
}
public class C<T> where T : class // maybe you want to add other "where" constraints on T
{
public void Do()
{
// you can use T in here
}
}