I am fairly new to c# and very new to abstract classes. Below is an example of the code I am writing. I instantiate my object with Parent obj = new Child2(); or Parent obj = new Child3();
Note that the purpose of this is Child 2 and 3 have different properties but some common, overloaded methods.
My problem is that I can not see any properties in the child class
if I have not described the question in enough detail, please let me know and I will elaborate
namespace ns
{
public class Parent
{
public abstract DataTable ImportToDataTable()
}
public class Child2 : Parent
{
public DelimitedFileDetail InputFile = new DelimitedFileDetail();
public string PropertyforChild1 { get; set; }
public override DataTable ImportToDataTable() { .....code }
}
public class Child3 : Parent
{
public string PropertyforChild2 { get; set; }
public override DataTable ImportToDataTable() { .....code }
}
public class DelimitedFileDetail : Child2
{
public string Name { get; set; }
public ImportTypes FileType { get; set; }
public List<FieldDefinitions> FieldList = new List<FieldDefinitions>();
}
}
You should define your Parent class to be an interface instead of abstract class or base class for that matter
This way your child classes can implement the interface. Then you should use the interface variable to reference child classes/implementations.
Is there a reason you have defined Parent as abstract class? An interface should do since you haven't implemented any abstract members anyway
Well, when you declare the variable in c# with the Parent type, intelisense won't show you the properties of the child.
If you want to use the specific properties of the children you need to declare the variable with the type of the specific children.
So instead of doing:
Parent obj = new Child2();
You should do:
Child2 obj = new Child2();
And so for...
You can't see any properties of the child class because you've told the compiler that obj is of type Parent. If you want to see the properties of the child class you can cast obj to the true type:
Parent obj = new Child2();
string str = ((Child2)obj).PropertyforChild2;
This is, of course, not ideal code. Mostly because then you have to know that obj is of type Child2 and if you know that, why not just give obj the type Child2?
Related
I have two classes which should be exactly the same apart from 1 class needed another property.
Instead of re-writing all of the properties twice, I thought of inheriting all of the properties from BaseClass with just the one extra property in MyNewClass
public class BaseClass
{
public int BaseProperty1 { get; set; }
public int BaseProperty2 { get; set; }
public int BaseProperty3 { get; set; }
}
public class MyNewClass: BaseClass
{
public int? ExtraProperty{ get; set; }
}
Since I already fill in all of the details for the original BaseClass in my function, It would be far easier to be able to use this instance of the class to fill in the details of the new instance of MyNewClass.
I hoped it would be as simple as the following, but unfortunately I get the error: System.InvalidCastException: 'Unable to cast object of type 'BaseClass' to type 'MyNewClass'.'
MyNewClass myNewClass= new MyNewClass();
myNewClass = (MyNewClass)baseClass; //baseClass is alread populated at this point
myNewClass.ExtraProperty = 1;
Is there any way to quickly populate a class using another class which has one less property?
I could just set each property individually, but the class which I am using is quite large and it feels like bad practice.
Thanks in advance for any help.
Not every fruit is an apple, so from compiler perspective not every BaseClass is an instance of MyNewClass hence the cast fails.
There are couple of things you can do. For example use constructor to populate values:
public class MyNewClass : BaseClass
{
public int? ExtraProperty { get; set; }
public MyNewClass(BaseClass baseClass)
{
BaseProperty1 = baseClass.BaseProperty1;
BaseProperty2 = baseClass.BaseProperty2;
BaseProperty3 = baseClass.BaseProperty3;
}
}
Then you can do:
var myNewClass = new MyNewClass(baseClass);
myNewClass.ExtraProperty = 1;
If you have a lot of properties and don't want manually set every each of them then I suggest you iterate through them like this
public class MyNewClass : BaseClass
{
public MyNewClass(BaseClass seizeProperties)
{
PropertyInfo[] baseProperties = typeof(BaseClass).GetProperties();
foreach (PropertyInfo property in baseProperties)
{
property.SetValue(this, property.GetValue(seizeProperties));
}
}
public int? ExtraProperty { get; set; }
}
"I already fill in all of the details for the original BaseClass in my function"
So, if you have func like
void your_func_fill(BaseClass _BaseClass)
you can just call this func with child class object
MyNewClass _MyNewClass;
...
your_func_fill(_MyNewClass)
Good luck!
I have three classes, two of which inherit from a base class, and the third which I would like to reference one of the other two depending on the state of the application.
public class Batch
{
public Batch() { }
}
public class RequestBatch : Batch
{
public RequestBatch(string batchJobType) : base(batchJobType) { }
public override int RecordCount
{
get { return Lines.Count; }
}
}
public class ResponseBatch : Batch
{
public ResponseBatch(string batchJobType) : base(batchJobType) { }
public ResponseBatch(int BatchJobRunID)
{ }
}
Sometimes I have an instance of Child1 instantiated, and sometimes I need Child2. However, I have model that I want to pass around my application to keep everything in one place, but I want a way to make the property that holds Child1 and Child2 generic, for example:
public class BatchJob {
public List<Batch> Batches { get; set; }
}
And then later do this
public List<RequestBatch> GetBatches(...) {}
var BatchJob = new BatchJob();
BatchJob.Batches = GetBatches(...);
However, the compiler yells at me saying it can't implicitly convert Child1 to (its base type) Parent.
I get red squiggles under "= GetBatches(...." saying "Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
Is there a way to generify the Property so it can take any abstract of type Parent?
Thanks!
The code snipped you show does work. There is no compiler error:
class Program
{
static void Main()
{
var rj = new RunningJob();
rj.Property = new Child1();
rj.Property = new Child2();
}
}
public class RunningJob {
public Parent Property { get; set; }
}
public class Parent { }
public class Child1 : Parent { }
public class Child2 : Parent { }
The only issue that comes with this code is that Property is of type Parent. So you cannot call methods that are specific for Child1/Child2. This can be done using constraints on generic type parameters on class RunningJob :
public class RunningJob<TParent> where TParent : Parent
{
public TParent Property { get; set; }
}
Hence, now it is ensured that Property is of type Parent or any derived types.
One option...
public new IEnumerable<RequestBatch> GetBatches(...) {
get
{
return base.GetBatches(...).OfType<RequestBatch>();
}
}
Another...
If you don't need to modify the collection then just change from List<T> to IEnumerable<T>
More Info...
Covariance and Contravariance in Generics
A contravariance conundrum
I don't know if this is possible, but I am trying to get the Base Class instance from a Derived Class. In C#, I can use the base keyword to access properties and methods of the Base Class (of course), but I want to use base itself. Attempting to do so results in a "Use of keyword 'base' is not valid in this context" error.
Example Code
public class SuperParent
{
public int SPID;
public SuperParent()
{
}
}
public class SubChild : SuperParent
{
public SubChild(int pSPID)
{
base.SPID = pSPID;
}
public int BaseSPID
{
get
{
SuperParent sp = base;
return sp.SPID;
}
}
}
If you're working with an instance of the derived class, there is no base instance.
An example:
class A
{
public void Foo() { ... }
}
class B : A
{
public void Bar() { ... }
}
What is not possible within B:
public void Bar()
{
// Use of keyword base not valid in this context
var baseOfThis = base;
}
You can do something like this:
public void Bar()
{
base.Foo();
}
And you can add another method like
public A GetBase()
{
return (A)this;
}
And then you can
public void Bar()
{
var baseOfThis = GetBase();
// equal to:
baseOfThis = (A)this;
}
So this GetBase() method is probably what you want.
The punchline is: If you have an instance of B, it inherits all properties and the non-overriden behaviour of A, but it does not consist of an instance of B which holds an (hidden but automatic) reference to an instance of A. You can cast your B instance to A, but it remains to be an instance of B.
Well you not provide code for your question, but i supsect you want something like
class Base
{
public virtual void Foo()
{
Console.WriteLine("base");
}
}
class Derived : Base
{
public override void Foo()
{
Console.WriteLine("derived");
}
//// bad
//public Base MyBase
//{
// get
// {
// return base; // Use of keyword 'base' is not valid in this context
// }
//}
// work but...
public Base MyBase
{
get
{
return (Base)this;
}
}
}
But keep in mind that MyBase is really of type Derived
new Derived().MyBase.Foo(); // output "derived"
the problem hasn't been explained as clearly as it could. however, typically, you may be better to use an abstract base class and methods and then override the required methods. you can then use the base.method as required in this case (otherwise you'll have just spun up an instance of the derived class).
public abstract class foo {
public virtual void bar(){..}
}
public class footwo : foo {
public override void bar(){
// do somethng else OR:
return base.bar();
}
}
}
The derived instance IS the base instance. It's just one object instance in memory.
example:
public class A : B
{
}
var thing = new A();
thing is an instance of an A, and is also an instance of a B.
You could for example, write this line:
B thing2 = thing;
Point 1: if you want to create the base class instance within child class than it does not worth. You already have public things accessible in child.
Point 2: If you have initialized child class and now want to get base class "instance" then how can you get that if it's not initialized(Because now the base class instance is not present in the physical memory, and there is just child class instance there)?
I interpreted what they were asking a bit differently than the other answers here so I figured I would offer my $0.02.
// Create a "Parent" class that has some attributes.
public class Parent
{
public string attribute_one { get; set; }
public string attribute_two { get; set; }
public string attribute_three { get; set; }
}
// Define a class called "Child" that inherits the
// attributes of the "Parent" class.
public class Child : Parent
{
public string attribute_four { get; set; }
public string attribute_five { get; set; }
public string attribute_six { get; set; }
}
// Create a new instance of the "Child" class with
// all attributes of the base and derived classes.
Child child = new Child {
attribute_one = "interesting";
attribute_two = "strings";
attribute_three = "to";
attribute_four = "put";
attribute_five = "all";
attribute_six = "together";
};
// Create an instance of the base class that we will
// populate with the derived class attributes.
Parent parent = new Parent();
// Using reflection we are able to get the attributes
// of the base class from the existing derived class.
foreach(PropertyInfo property in child.GetType().BaseType.GetProperties())
{
// Set the values in the base class using the ones
// that were set in the derived class above.
property.SetValue(parent, property.GetValue(child));
}
The result is a new object populated with the base class properties of the child class.
class Parent
{
private Parent _parent;
public Parent()
{
_parent = this;
}
protected Parent GetParent()
{
return _parent;
}
}
class Child : Parent
{
private Parent _parent;
public Child()
{
_parent = base.GetParent();
}
}
If I have the class:
class NodeA
{
public string Name{get;set;}
public List<NodeA> Children {get;set;}
// etc some other properties
}
and some other class:
class NodeB
{
public string Name;
public IEnumerable<NodeB> Children;
// etc some other fields;
}
If I need to convert a NodeB object to of type NodeA what will be the best approach? Create a wrapper class? If I have to create a wrapper class how could I create it so that all the wpf controls will still be able to successfully bind to the properties?
Reason why I need to create such cast:
There was an old algorithm that was used on a program that return the list of symbols (IMemorySymbol) in a compiled program. We have worked and created a new algorithm and the fields and properties are somewhat different (ISymbolElem). We need to perform a temporary cast in order to display the properties in the view of the wpf application.
A couple approaches...
Copy Constructor
have a NodeA and NodeB contain a constructor which takes the opposite:
class NodeA
{
public string Name{get;set;}
public List<NodeA> Children {get;set;}
// COPY CTOR
public NodeA(NodeB copy)
{
this.Name = copy.Name;
this.Children = new List<NodeA>(copy.Children.Select(b => new NodeA(b));
//copy other props
}
}
Explicit or Implicit Operator
http://msdn.microsoft.com/en-us/library/xhbhezf4.aspx
http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx
explicit you would cast like NodeA a = (NodeA)b;, while implicit you can skip the parens.
public static explicit operator NodeA(NodeB b)
{
//if copy ctor is defined you can call one from the other, else
NodeA a = new NodeA();
a.Name = b.Name;
a.Children = new List<NodeA>();
foreach (NodeB child in b.Children)
{
a.Children.Add((NodeA)child);
}
}
If you don't care about coupling the implementation of NodeA to NodeB, then add a copy constructor as follows:
class NodeA
{
public NodeA() { }
public NodeA(NodeB node)
{
Name = node.Name;
Children = node.Children.Select(n => new NodeA(n)).ToList();
}
public string Name{get;set;}
public List<NodeA> Children {get;set;}
// etc some other properties
}
If coupling is a concern, then you can create a Convert-style class that does the conversion for you. Note that the Automapper framework generates these types of conversions for you by use of reflection over the source and target types.
How about inheriting from a common interface?
interface INode {
public string Name{get;set;}
public IEnumerable<INode> Children {get;set;}
}
class NodeA : INode {
public string Name{get;set;}
public List<NodeA> Children {get;set;}
// etc some other properties
}
class NodeB : INode {
public string Name;
public IEnumerable<NodeB> Children;
// etc some other fields;
}
void myMethod() {
INode nodeB = new NodeB();
INode nodeA = nodeB;
}
public void GetProps(Parent p){
// want to access lots of child properties here
string childProp1 = p.prop1;
bool childProp2 = p.prop2;
bool childProp3 = p.prop3;
}
However compiler complains that
"Parent does not contain definition prop1"
The function would take in different subtypes of Class Parent.
All the subclasses have this
public override string prop1 { get; set; }
Is there a way of accomplishing this?
EDIT:
To make the question clearer
I current have a giant if-elseif where i do something like
if(p is Child0){
Child0 ch = p as Child0;
// want to access lots of child properties here
string childProp1 = ch.prop1;
bool childProp2 = ch.prop2;
bool childProp3 = ch.prop3;
}else if(p is Child1){
Child1 ch = p as Child1;
// want to access lots of child properties here
string childProp1 = ch.prop1;
bool childProp2 = ch.prop2;
bool childProp3 = ch.prop3;
}else if(...// and many more
Now I wanted to remove all the redundant code and make one function that can handle all this.
If all child classes need to have the properties (but with different implementations), you should declare them as abstract properties in the base class (Parent), then implement them in the child classes.
If some derived classes won't have those properties, then what would you expect your current GetProps to do?
EDIT: If you're using C# 4 and you definitely can't get a better class design (where the parent class declares the property) you could use dynamic typing:
public void GetProps(Parent p) {
dynamic d = p;
string childProp1 = d.prop1;
bool childProp2 = d.prop2;
bool childProp3 = d.prop3;
// ...
}
I'd treat this as a last resort though...
The solution in case someone need it, it is just to cast the class you receive as a reference as follows:
public void GetProps(Parent p){
..
string childProp1 = ((ChildClass)p).prop1;
...
}
As I understood from your question, you want to access Children Class members from object of Parent Class.
This behavior is not allowed in OOP.
One way can be as suggested by Jon Skeet to create a Abstract base class and implement the required members in Children Classes.
Other way round can be to assign the required values to members of base class in derived class constructor using base construct. I do not know this will solve your problem or not. But Consider the following snippet for example:
public class BaseClass
{
public string FirstName = "Base Class";
public string LastName = "Base Class";
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
base.LastName = "Derived Class";
}
}
internal class Tester
{
private static void Main(string[] args)
{
BaseClass objBaseClass = new BaseClass();
Console.WriteLine("First Name : " + objBaseClass.FirstName);
Console.WriteLine("Last Name : " + objBaseClass.LastName);
DerivedClass objDerivedClass = new DerivedClass();
Console.WriteLine("First Name : " + objDerivedClass.FirstName);
Console.WriteLine("Last Name : " + objDerivedClass.LastName);
BaseClass objBaseDerivedClass = new DerivedClass();
Console.WriteLine("First Name : " + objBaseDerivedClass.FirstName);
Console.WriteLine("Last Name : " + objBaseDerivedClass.LastName);
Console.ReadKey();
}
}
O/P
First Name : Base Class
Last Name : Base Class
First Name : Base Class
Last Name : Derived Class
First Name : Base Class
Last Name : Derived Class
Let me know, if it helps out.
If the property is defined in an intermediate class between parent and child and you don't have a reference to that intermediate class at design time then you could use reflection to get the property. But it sounds like you should be using the most relevant sub parent instead of simply parent.
If I understood you correctly (- I'm assuming Parent is a base class from which Child0 Child1 etc inherit.) – you're just missing a declaration of prop1 in the parent. It won't get in the way, it will simply be overridden.
Check out this example (which returns "child string") and note that child is passed to a method that expects a ParentClass instance.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ChildClass child = new ChildClass();
Text = ParentClass.mymethod(child);
}
}
class ParentClass
{
public virtual string s { get { return "parent string"; } }
public static string mymethod(ParentClass parent)
{
return parent.s;
}
}
class ChildClass : ParentClass
{
public override string s { get { return "child string"; } }
}