|
That's correct (unless you cast it). That's kind of an unavoidable consequence of putting any method on the base class. Typically in an abstract class hierarchy, the base class will define (either concrete or abstract) most of the public interface, so you can do most things through the base.
If you know that you are working with D1, after all, you can just create a new instance with new D1() . The dynamic Create method is only needed when you want a new instance of the same type as another object, and you don't know what type that is, so you wouldn't be able to call class-specific functionality on it anyway.
|
|
|
|
|
Thank you for your clear answer.
So:
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
even if newClassAb is a D1 type, I cannot use D1 methods unless cast it.
So no way to avoid to write the same piece of code in each derived class even if they basically do the same thing, if I want to use all methods of derived class. Is it?
class D1:b
{
..
public D1 Create() { return new D1(); }
}
class D2 : b
{
..
public D2 Create() { return new D2(); }
}
|
|
|
|
|
You can use generics like this:
abstract class b<T> where T: b, new()
{
...
public T Create() { return new T(); }
}
class D1 : b<D1>
{
...
}
class D2 : b<D2>
{
...
}
So, you can do:
D1 myClassD1 = new D1();
D1 newClassD1 = D1.Create();
But, you can't do anymore:
b myClassAb = new D1;
D1 newClassAb = myClassAb.Create();
because you'd have to specify the generic type for class b.
|
|
|
|
|
Now you can't call Create on an arbitrary b instance, which renders it pointless.
|
|
|
|
|
I said that at the end of my post.
I agree you are losing many advatages of polymorphism, but, at least, you can reuse the Create login in multple classes.
|
|
|
|
|
There's a very simple way, if you know you want a D1: call new D1() not myD1Instance.Create() .
I'm guessing this is a simplified example, because it simply doesn't make sense to do things this way in most cases. What is your actual problem?
Accepting for the moment that you need a Create method at all: If you know that an instance of b is actually a D1 (for example within the D1 class itself) then you can cast the result of Create safely. Casting is not necessarily bad (it's safer than the use of dynamic, I would say). For example, in some similar code to what I have at the moment for cloning objects in an inheritance tree:
class b {
private int someField;
public b Copy() {
b newB = Create();
CopyTo(newB);
return newB;
}
protected virtual void CopyTo(b newB){
newB.someField = someField;
}
class D1 : b {
private double derivedField;
protected override void CopyTo(b newD1){
D1 target = (D1)newD1;
target.derivedField = derivedField;
}
}
Outside the class tree, it's unlikely that you know for sure at compile time which of the classes you have an instance of (otherwise you wouldn't need the abstract base class at all), so you can normally only cast the result inside the class, or using if(my is D1) type tests. And if you find yourself writing those you probably just found somewhere that an abstract method should be provided on the base class.
|
|
|
|
|
Actually, you don't need Visual Studio at all. What you are meaning to say is "this requires .NET 4.0"
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace general
{
class Program
{
static void Main(string[] args)
{
D1 myClass = new D1();
D1 newClass = myClass.Create();
//this is what I would like
b myClassAb = new D1();
b newClassAb = myClassAb.Create<D1>();
newClass.KM = 1.23;
}
}
abstract class b
{
//work in this way !!!
public T Create<T>() where T:new() { return new T(); }
}
class D1 : b
{
public double KM;
public D1() { KM = 1.0; }
// public D1 Create() { return new D1(); }
}
class D2 : b
{
public double KM;
public D2() { KM = 2.0; }
// public D2 Create() { return new D2(); }
}
}
here is one solution using generics
modified on Wednesday, June 1, 2011 9:53 AM
|
|
|
|
|
Sorry probably I did not explain very well the problem. I need to have avaiable methods in newClassAb
//this is what I would like
b myClassAb = new D1();
b newClassAb = myClassAb.Create<D1>();
//This is what I need to see K from newClassAb
Console.WriteLine(newClassAb.K)>//but I can't see .K avaiable
Thanks for your time
modified on Wednesday, June 1, 2011 7:32 AM
|
|
|
|
|
what is K is it KM well i can see KM
try it once more because there was some error in my code
|
|
|
|
|
b myClassAb = new D1();
b newClassAb = myClassAb.Create<D1>();
newClassAb.KM = 1.23;
apparently return this error" Error 1 'general.b' does not contain a definition for 'KM' and no extension method 'KM' accepting a first argument of type 'general.b' could be found (are you missing a using directive or an assembly reference?)"
The working solution example, thanks to BobJanova is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace general
{
class Program
{
static void Main(string[] args)
{
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
Console.WriteLine(newClassAb.KM);
}
}
abstract class b
{
public double KM { get; protected set; }
public b Create() { return (b)Activator.CreateInstance(GetType()); }
}
class D1 : b
{
public D1() { KM = 1.0; }
}
class D2 : b
{
public D2() { KM = 2.0; }
}
}
|
|
|
|
|
In response to your modification: KM should clearly be defined on the base class. It should probably also be a property.
abstract class b
{
public double KM { get; protected set; }
public b Create() { return Activator.CreateInstance(GetType()); }
}
class D1:b
{
public D1() { KM = 1.0; }
}
class D2 : b
{
public D2() { KM = 2.0; }
}
|
|
|
|
|
Console.WriteLine(b.//<big>b.KM is still not avaiable!!</big>}
namespace general
{
class Program
{
static void Main(string[] args)
{
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
Console.WriteLine(b.
}
abstract class b
{
public double KM { get; protected set; }
public b Create() { return (b)Activator.CreateInstance(GetType()); }
}
class D1 : b
{
public D1() { KM = 1.0; }
}
class D2 : b
{
public D2() { KM = 2.0; }
}
|
|
|
|
|
You should be able to use newClassAb.KM.
|
|
|
|
|
Great!!!! It works...Thanks a lot
|
|
|
|
|
I am sorry but, what is the point in creating an instance of a class to just create another instance of the same class? I mean, since Create method is not static it would just work as a constructor so, why don't you just use a constructor?
For example, what you want to do is this:
D1 obj = new D1();
D1 obj2 = D1.Create();
And what I am saying is... why not?
D1 obj = new D1();
D1 obj2 = new D1();
I guess you want a static Create method in your base class, don't you? In this case you will have to make your Create method static and use generics:
abstract class BaseClass
{
public static T Create<T>() where T : BaseClass, new()
{
return new T();
}
}
class DerivedClass : BaseClass { }
This way you could use it like this:
DerivedClass obj = BaseClass.Create<DerivedClass>();
|
|
|
|
|
I was looking for a way to avoid to write the same piece of code in each derived class since they basically do the same thing. I Would like to create a method in the base class. But this should allow you to use methods of derived class Is it?
class D1:b
{
..
public D1 Create() { return new D1(); }
}
class D2 : b
{
..
public D2 Create() { return new D2(); }
}
So my goal is not to do
D1 obj = new D1();
D1 obj2 = D1.Create();
but to do
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
Console.WriteLine(newClassAb.KM);
|
|
|
|
|
Member 4282287 wrote: I need to access to proprieties, methods, etc of class
That does not depend on how you create the objects, I mean, your Create method will not help you to achieve what you want. If you can access KM property of a D1 object which you have declared as its base class type (b in this case), you can becouse KM property is definied within the "b" class interface, but not becouse you have made such a strange Create method. So in your sample:
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
Console.WriteLine(newClassAb.KM)
You don't need the Create method at all. Just use the constructor and one instance of the object:
b myClassAb = new D1();
Console.WriteLine(myClassAb.KM)
|
|
|
|
|
ok thanks understood.
Really the starting example was a bit different ... i.e. I needed a method avaiable only in derived class.
During the forum this method ... become a proprierties..
Apparently I understood. You are right of course.
Thanks for your time
|
|
|
|
|
Hi All,
i googled how we can added events in C# class for COM Interop that can be called in VB6.0 but not able to find out any article that help me.
if any one tried it before then pls guide me.
here is my code.
public interface ICalculator
{
// I guess we need to add a event here but i am not sure .
int Add(int Number1, int Number2);
}
public class ManagedClass:ICalculator
{
public int Add(int Number1,int Number2)
{
// I want to raise an event here so that this event should be consumed in VB
return Number1+Number2;
}
}
i done all the step to make the dll to be used in VB.
|
|
|
|
|
COM interop is supposed to work with normal .Net events (i.e. event EventHandler<MyEventArgs> Calculate ), isn't it? The problem here might be VB6 ...
|
|
|
|
|
You have to play a bit with interfaces.
Look here for a sample.
|
|
|
|
|
You'd need to declare the object WithEvents in VB6, otherwise VB6 won't hook those up. Microsoft made a toolkit[^] to make interop between VB6 and .NET a lot easier. I suggest you download it and have a look. There's also a CodeProject article[^] on the subject.
Bastard Programmer from Hell
|
|
|
|
|
I'm not sure about COM interop stuff as I've never needed it - but events are quite straight forward to add:
public interface ICalculator
{
event EventHandler CalculationPerformed;
event EventHandler<int> CalculatedResult;
int Add(int Number1, int Number2);
}
public class ManagedClass : ICalculator
{
public event EventHandler CalculationPerformed;
public event EventHandler<int> CalculatedResult;
public int Add(int number1, int number2)
{
int result = number1 + number2;
OnCalculationPerformed(EventArgs.Empty);
OnCalculatedResult(new EventArgs<int>(result));
return result;
}
protected virtual void OnCalculationPerformed(EventArgs e)
{
EventHandler eh = CalculationPerformed;
if (eh != null)
eh(this, e);
}
protected virtual void OnCalculatedResult(EventArgs<int> e)
{
EventHandler<int> eh = CalculatedResult;
if (eh != null)
eh(this, e);
}
}
public delegate void EventHandler<T>(object sender, EventArgs<T> e);
public class EventArgs<T> : EventArgs
{
private T value;
public EventArgs(T value)
{
this.value = value;
}
public T Value
{
get { return value; }
}
}
|
|
|
|