I've got the following question.
I've got one class "Instellingen" that's a field in 3 other classes
public class Instellingen
{
private int _ID;
}
public class Class1: Button
{
private Instellingen _Instellingen;
}
public class Class2 : Label
{
private Instellingen _Instellingen;
}
public class Class3 : TextBox
{
private Instellingen _Instellingen;
}
If I've got another class, that uses the other classes (but it can be anyone of this 3 classes)
Do i have to use a switch? or is there an easier way?
public class AnotherClass
{
public AnotherClass ()
{
GetInstellingenFromClass(new Class1());
GetInstellingenFromClass(new Class2());
GetInstellingenFromClass(new Class3());
}
private void GetInstellingenFromClass(Control c)
{
switch (c.GetType.ToString())
{
case "Class1":
Class1 klasse = (Class1) c;
//Do something with the _Instellingen of this class
break;
case "Class2":
Class2 klasse2 = (Class2) c;
//Do something with the _Instellingen of this class
break;
case "Class3":
Class3 klasse3 = (Class3)c;
//Do something with the _Instellingen of this class
break;
}
}
}
(does there exists something so i can just do something like c._Instellingen --> without converting it first to the right type, where it doesn't matter what type c is?)
I hope you understand my question.
Thanks
You should make an interface that has an Instellingen property and implement it in the three classes.
For example:
interface IHasInstellingen {
Instellingen Instellingen { get; }
}
public class Class1: Label, IHasInstellingen {
public Instellingen Instellingen { get; private set; }
}
public class Class2: Button, IHasInstellingen {
public Instellingen Instellingen { get; private set; }
}
private void GetInstellingenFromClass(IHasInstellingen c) {
Instellingen ig = c.Instellingen;
//Do things...
}
//Alternatively:
private void GetInstellingenFromClass(Control c) {
IHasInstellingen hi = c as IHasInstellingen;
if (hi == null)
return; //Or throw an ArgumentException
Instellingen ig = hi.Instellingen;
//Do things...
}
No, you don't have to use a switch. Actually the concept Interface is what you are looking for. Something like;
public interface IIntelingenProvider
{
Intelingen Item {get;}
}
public class Class1: Label, IIntelingenProvider
{
private Instellingen _Instellingen;
public Intelingen Item { get { return _Instellingen; } }
}
public class Class2: Label, IIntelingenProvider
{
private Instellingen _Instellingen;
public Intelingen Item { get {return _Instellingen; } }
}
And the type you are going to provie to the GetInstellingenFromClass method would be IIntelingenProvider. Hence you can write it as;
private void GetInstellingenFromClass(IIntelingenProvider c)
{
// regardless of the type, they all have an Item property of type Intelingen
// c.Item
}
I suggest you to read and learn more about Interitance and Polymorphism
Polymorphism. In your case, all classes extend Label, so you could have Label define your Instellingen:
public class Label
{
public Instellingen Instellingen
{
get { return ...; }
}
}
Then AnotherClass can just work with Labels:
private void GetInstellingenFromClass(Label l)
{
var instellingen = l.Instellingen;
// do something with instellingen here
}
Of course, if you don't own the Label class you can always subclass it and use that from your classes. Another option is to define an interface with the property and have AnotherClass depend on that interface.
Instead of having each of your three classes derive from Label, can you create an intermediate base class, like LabelWithInstellingen?
Consider using an interface to expose an Instellingen property in the classes that need them.
class Instellingen
{
public int ID { get; set; };
}
interface IHasInstellingen
{
Instellingen Instellingen { get; set; }
}
class MyLabel: Label, IHasInstellingen
{
public Instellingen Instellingen { get; set; }
}
class MyButton: Button, IHasInstellingen
{
public Instellingen Instellingen { get; set; }
}
class AnotherClass
{
public AnotherClass ()
{
GetInstellingenFromClass(new MyLabel());
GetInstellingenFromClass(new MyButton());
// ...
}
private void GetInstellingenFromClass(IHasInstellingenc)
{
Console.WriteLine( c.Instellingen.ID );
// ... Do something with Instellingen
}
}
Related
I need to create a dll file which contains all the interfaces of the classes but doesn't contain any class.
Because I use these interfaces for a lot of classes it's must be like that:
public interface IClassA
{
string Word { get; }
}
public interface ITest<TClassA> where TClassA : IClassA
{
TClassA A { get; }
}
Example of two classes that implements these interfaces the way I want:
public class ClassA : IClassA
{
public string Word
{
get;
private set;
}
public string Sentence
{
get;
private set;
}
public ClassA(string word, string sentence)
{
this.Word = word;
this.Sentence = sentence;
}
}
public class Test : ITest<ClassA>
{
public ClassA A
{
get;
private set;
}
public Test(ClassA a)
{
this.A = a;
}
}
And I want to do something like that in the main program:
public static void Main(string[] args)
{
ClassA a = new ClassA("hey", "hey world!");
Test t = new Test(a);
Print((ITest<IClassA>)t);
}
public static void Print(ITest<IClassA> t)
{
Console.WriteLine(t.A.Word);
}
But this casting: (ITest<IClassA>)t makes a run time error.
How can I solve it?
thanks!
You should declare Test as
public class Test : ITest<IClassA>
instead of ITest<ClassA>.
Or declare ITest<TClassA> to be covariant on TClassA:
public interface ITest<out TClassA> where TClassA : IClassA
The Test-class implements the concrete ClassA (public class Test : ITest<ClassA>).
So you're trying to cast an ITest<ClassA> to ITest<IClassA> which obviously fails.
If you let the Test-class implement IClassA, the cast works:
public class Test : ITest<IClassA>
{
public IClassA A
{
get; private set;
}
public Test(IClassA a)
{
this.A = a;
}
}
I'm trying to create instance of class Bar but I'm receiving an error:
"Cannot implicitly convert type ConsoleApplication1.Bar to
ConsoleApplication1.BaseFoo<ConsoleApplication1.baseOutput,
ConsoleApplication1.baseInput>"
Any idea what I'm missing or what I'm doing wrong? Any advice will be nice.
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public class BaseFoo<baseOutput, baseInput>
{
protected virtual void DoSmth()
{
}
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
protected override void DoSmth()
{
base.DoSmth();
}
}
public class Test
{
public void Show()
{
}
private BaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar(); // Error right here
}
}
I'll give you an example of why you're prevented from doing that.
Imagine instead, your classes were written like this:
public class BaseFoo<TOutput, TInput>
where TOutput : BaseOutput
{
public TOutput Something { get; set; }
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
}
public class BaseInput { }
public class BaseOutput { }
public class ExtendOutput : BaseOutput { }
public class SomethingElse : BaseOutput { }
Now, you have this method:
private BaseFoo<BaseOutput, BaseInput> CreateInstance()
{
//At this point, Something will be of type ExtendOutput.
return new Bar();
}
So, we call it like this:
var myBar = CreateInstance();
Now, mybar.Something is of type BaseOutput. That's fine, though, because ExtendOutput : BaseOutput, right? Not quite.
What happens when we do this:
myBar.Something = new SomethingElse();
That's valid, because Something expects a BaseOutput, and SomethingElse is a BaseOutput. However, the object is actually a Bar, which explicitly says it should be an ExtendOutput.
The problem is clearer if we attempt to cast it back:
var myBaseFoo = CreateInstance();
myBaseFoo.Something = new SomethingElse();
Bar myBar = (Bar)myBaseFoo;
myBar.Something; // Here, we're told it's going to be an `ExtendOutput`,
// but we get a `SomethingElse`?
That's clearly wrong. And that's why you're prevented from doing what you're trying to do. You can have this behavior with covariance.
Covariance makes it illegal to pass in a TOutput. So, this line
public TOutput Something { get; set; }
Would be invalid. We would only be allowed to expose the getter:
public TOutput Something { get; }
Which alleviates the above problem
Bar is BaseFoo<ExtendOutput, ExtendInput>, and CreateInstance() requires BaseFoo<baseOutput, baseInput> to be returned, so it can't return Bar which is BaseFoo<ExtendOutput, ExtendInput>.
Regardless ExtendOutput inherits baseOutput, when you inherit a generic class the inheritance is invariant.
Consider using interfaces with in and out generic modifiers:
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public interface IBaseFoo<out T1, out T2>
{
public void DoSmth();
}
public class Bar : IBaseFoo<ExtendOutput, ExtendInput>
{
public void DoSmth()
{
}
}
public class Test
{
public void Show()
{
}
private IBaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar();
}
}
I am inheriting some System.Windows.Forms-Control (about 10 pieces).
Each of them gets some custom extensions, but most of the extension will be the same for each control.
Actually I have to code the same functionality separate for each of them.
This is a lot of copy+paste and difficult to maintain.
class MyButton : Button
{
//this is only in MyButton
public int ButtonProperty { get; set; }
public object Property1 { get; set; }
public object Property2 { get; set; }
public void MakeInvisible()
{
this.Visible = false;
}
}
class MyLabel : Label
{
//this is only in MyLabel
public bool LabelProperty { get; set; }
//same propertys and methods as in MyButton
public object Property1 { get; set; }//copy+paste
public object Property2 { get; set; }//copy+paste
public void MakeInvisible()//copy+paste
{
this.Visible = false;
}
}
What I am searching for is a way to extend all of the derived classes like you can do with an interface or extension method. But I also want to have properties and access the base class (Control)
This is what I am dreaming about:
class MyButton : Button, MyExtension
{
//this is only in MyButton
public int ButtonProperty { get; set; }
}
class MyLabel : Label, MyExtension
{
//this is only in MyLabel
public bool LabelProperty { get; set; }
}
//Extension for all classes inherited from Control
class MyExtension : Control
{
public object Property1 { get; set; }
public object Property2 { get; set; }
public void MakeInvisible()
{
this.Visible = false;
}
}
idea:
create a new type for common properties
give each control a property of that type
implementation:
// TypeConverter required for PropertyGrid in design mode
// found here: http://stackoverflow.com/a/6107953/1506454
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyExtension
{
// need reference to control to work with in methods
private Control _c;
public MyExtension(Control c)
{
_c = c;
}
// can be inhereted for different controls, if necessary
public string Property1 { get; set; }
public string Property2 { get; set; }
public void MakeInvisible()
{
_c.Visible = false;
}
}
// common interface of extended controls
public interface IExtended
{
MyExtension Extra { get; }
}
// MyButton implements extended interface
public class MyButton : Button, IExtended
{
public MyButton()
{
// create extended properties for button
Extra = new MyExtension(this);
}
// for designer serialization support
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public MyExtension Extra { get; private set; }
//this is only in MyButton
public int ButtonProperty { get; set; }
}
// common extension methods
public static class MyControlHelper
{
public static void MakeInvisible<TControl>(this TControl control) where TControl : Control, IExtended
{
control.Extra.MakeInvisible();
}
public static void Rename<TControl>(this TControl control) where TControl : Control, IExtended
{
control.Text = control.Extra.Property1;
}
}
C# doesn't support multi inheritance. You should try something like this - MyButton : MyExtension; and MyExtension : Button. In this case you will extend MyButton class with MyExtension and Button classes.
You can use extension methods for this purpose
public static class ControlHelper
{
public static void MakeInvisible(this Control c)
{
c.Visible = false;
}
}
and use it like this
var mb = new MyButton();
mb.MakeInvisible();
var ml = new MyLabel();
ml.MakeInvisible();
By using this approach you can generate extension methods for base classes and use it in derived classes.
Instead of inheriting from the Button and Label you could use composition.
class MyExtension
{
protected Control control;
public MyExtension(Control control)
{
this.control = control;
}
public object Property1 { get; set; }
public object Property2 { get; set; }
public void MakeInvisible()
{
this.control.Visible = false;
}
}
class MyButton : MyExtension
{
public MyButton(Button button):base(button){}
public int ButtonProperty { get; set; }
}
class MyLabel : Label
{
public MyButton(Label label):base(label){}
public bool LabelProperty { get; set; }
}
You could even make MyExtension abstract if you don't want any instances of it created. The main difference here is that you'll have to create a Button or Label to pass in and you might want to expose them as properties of your MyButton and MyLabel so you can get at their properties.
If you need to leverage protected methods and properties of the extended controls then you are out of luck, there is no way to acheive what you want without extensive copy and paste.
If you only need access to public methods and properties, then how about something along the following lines:
public interface IControlExtension
{
Foo MyProperty { get; set; }
Blah MyMethod();
}
public abstract class ControlExtension: IControlExtension
{
private Control owner;
private ControlExtension(Control owner)
{
Debug.Assert(owner != null);
this.owner = owner;
}
public static IControlExtension GetControlExtension(Control c)
{
if (c is Button ||
c is Label)
{
return new SimpleControlExtension(c);
}
if (c is Panel || ...
{
return new ContainerControlExtension(c);
}
}
public abstract Foo MyProperty { get; set; }
public abstract Blah MyMethod();
private class SimpleControlExtension: ControlExtension
{
public override Foo MyProperty { .... }
public override Blah MyMethod { ....
}
private class ContainerControlExtension: ControlExtension
{
public override Foo MyProperty { .... }
public override Blah MyMethod { .... }
}
}
Now, in all your extended controls, the copy and paste code is minimum:
public class MyButton : Button
{
public MyButton()
{
....
var controlExtension = ControlExtension.GetControlExtension(this);
}
public IControlExtension { get { return controlExtension; } }
}
I want to create a class that could hold any of a number of same type of classes. For example lets says I have a base class like follows:
public class BaseClass
{
public string MyBaseString
{
get;
set;
}
}
And then I have a few derived classes like this:
public class DerivedClass : BaseClass
{
public MyDerivedClassString
{
get;
set;
}
}
public class DerivedClass2 : BaseClass
{
public MyDerivedClass2String
{
get;
set;
}
}
Now I would like a class that accepts one of these implementations and does stuff with it. Here is the only thing I can think of, but there must be a better way:
public class ClassA
{
public object MyClass
{
get;
set;
}
public ClassA (object myClass)
{
MyClass = myClass;
if (object is BaseClass)
{
//do something
}
else if (object is DerivedClass)
{
//do something specific to derived class
}
else if (object is DerivedClass2)
{
//do something specific to derived class 2
}
}
}
CLARIFICATION: The specific goal I am trying to accomplish is to use ClassA as a container class for various implementations of the BaseClass. The business goal I am trying to accomplish is to create a Legend object which might use multiple color schemes (i.e. a Mono Color Ramp, Multi Color Ramp, etc). So I would like the Legend class to contain the ColorScheme that is being used, but still have access to that color scheme's unique properties for modification later on.
CLARIFICATION 2 Based on the wide array of responses I got, I thought I'd provide an exact replication of what I'm trying to do:
public class BaseColorScheme
{
List<Color> _colors = new List<Color>();
public List<Color> Colors
{
get
{
return _colors;
}
set
{
_colors = value;
}
}
}
public class SingleColorScheme : BaseColorScheme
{
public Color MidColor
{
get;
set;
}
public SingleColorScheme( Color midColor, int numberOfClassifications )
{
Colors = CreateMonoColorRamp( midColor, numberOfClassifications );
}
}
public class MultiColorScheme : BaseColorScheme
{
public Color StartColor
{
get;
set;
}
public Color EndColor
{
get;
set;
}
public Color MidColor
{
get;
set;
}
public MultiColorScheme( Color startColor, Color endColor, Color midColor )
{
StartColor = startColor;
EndColor = endColor;
MidColor = midColor;
Colors = //do something to define multi color scheme
}
}
Then I would have a Legend Class that would be something like
public class Legend
{
public object ColorScheme
{ get; set; }
public Guid LegendId
{ get; set; }
public Legend(object colorScheme)
{
ColorScheme = colorScheme;
}
}
Finally I might have a form that sits on top of the legend that displays the properties of the various color schemes based on which type of color scheme it is. Hopefully that helps clarify a bit.
public class ClassA<T> where T : BaseClass
{
public T MyClass { get; set; }
public ClassA(T myClass) { MyClass = myClass; }
}
Beyond that, define the common interface of the class hierarchy either as an interface or as methods (concrete, abstract, or virtual) within the base class. Then you can be assured all derived classes have such method / properties and can use them within your generic wrapper.
Instead of letting ClassA perform whatever needs to be done, you can use polymorphism and let the classes do it to themselves.
Simply declare a virtual method in the base class, have it do whatever you need it do so, and then override this method in the subclasses. In the method in ClassA, you just need to call that method on the object you receive as a parameter - without having to care about the specific type.
If you need to access different properties based on which derived class is passed something like this should help:
public class ClassA<T> where T : BaseClass
{
public T MyClass { get; set; }
public ClassA(T myClass) { MyClass = myClass; }
public void DoStuffToMyClass()
{
if(MyClass is BaseClass)
{ // do base class stuff }
else if(Myclass is DerivedClass)
{ // do DerivedClass stuff }
else if(MyClass is DerivedClass2)
{ // do DerivedClass2 stuff }
}
}
This gives you the type saftey to ensure you at least have the BaseClass object, and possibly a derived class.
The answer is polymorphism, let the object do it themselves.
public class BaseClass
{
public string MyString { get; set; }
public virtual string DoIt()
{
return "I'm Base Class";
}
}
public class DerivedClassA
{
public override string DoIt()
{
return "I'm Derived Class A";
}
}
public class DerivedClassB
{
public override string DoIt()
{
return "I'm Derived Class B";
}
}
....
public ClassA (BaseClass myClass)
{
MyClass = myClass;
MyClass.DoIt();
}
.....
ClassA x1 = ClassA(new BaseClass()) // calls BaseClass.DoIt()
ClassA x2 = ClassA(new DerivedClassA()) // calls DerivedClassA.DoIt()
ClassA x3 = ClassA(new DerivedClassB()) // calls DerivedClassB.DoIt()
whenever you catch yourself acting differently based on the run-time type of the object, you are dealing with code that breaks OO principles, i.e. a class that does not respect the base class contract.
Can you use virtual methods?
public abstract class BaseClass
{
public abstract void DoStuff();
}
public class DerivedClass1 : BaseClass
{
public override void DoStuff()
{
...
}
}
public class DerivedClass2 : BaseClass
{
public override void DoStuff()
{
...
}
}
Without generics:
public class ClassA
{
public BaseClass MyClass
{
get;
set;
}
public ClassA (BaseClass myClass)
{
MyClass = myClass;
myClass.DoStuff();
}
}
or with generics:
public class ClassA<T> where T : BaseClass
{
public T MyClass { get; set; }
public ClassA (T myClass)
{
MyClass = myClass;
myClass.DoStuff();
}
}
Keep it simple: polymorphism
Hopefully your objects have a common interface, something like:
class Base {
public virtual void DoSomething() { /* Default implementation */ }
}
class Derived1 : Base {
public override void DoSomething() { /* Implementation specific to this type */ }
}
class Derived2 : Base {
public override void DoSomething() { /* Another implementation specific to this type */ }
}
Or maybe they implement a common interface. So hopefully your consuming class can hold the most general representation of your inputs as possible and invoke code as such:
class Dependent {
public Dependent(Base instance) {
instance.DoSomething();
}
}
So your Dependent class doesn't really are whether it has a derived type or a base type.
Not quite as simple: visitor pattern
Sometimes polymorphism doesn't really work, which is particularly the case if you need to access the specific members of your derived classes, and those members aren't in the base class. Visitor pattern works well in this case, especially if you have a fixed, well-defined graph of objects.
public interface IVisitor<T> {
T Visit(Base x);
T Visit(Derived1 x);
T Visit(Derived2 x);
}
class Base {
public virtual T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); }
public string BaseString { get; set; }
}
class Derived1 : Base {
public override T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); }
public string Derived1String { get; set; }
}
class Derived2 : Base {
public override T Accept<T>(IVisitor<T> visitor) { visitor.Visit(this); }
public string Derived2String { get; set; }
}
So Derived1 and Derived2 have a different set of properties, and if you need to get to those properties without a runtime type-checking, implement a visitor:
class DefaultStringVisitor : IBaseVisitor<string> {
public string Visit(Base x) { return x.BaseString; }
public string Visit(Derived1 x) { return x.Derived1String; }
public string Visit(Derived2 x) { return x.Derived2String; }
}
class Dependent {
public Dependent(Base x) {
string whatever = x.Accept<string>(new DefaultStringVisitor());
}
}
So the visitor pattern gives you access to your derived object's members without a type-check. Its a somewhat inflexible pattern (i.e. need to know which objects to visit up front), but it might work for your needs.
I'm not even sure what this principle is called or how to search for it, so I sincerely apologize if it has been brought up before, but the best way to do it is with an example.
class Properties
{
public string Name { get; set; }
}
class MyClass
{
class SubProperties: Properties
{
public override Name
{
get { return GetActualName(); }
set { SetActualName(value); }
}
}
public SubProperties ClassProperties;
private string GetActualName()
{
return SomeFunction();
}
private void SetActualName(string s)
{
ClassProperties.Name = SomeOtherFunction(s);
}
}
The idea is to have any object that instantiates MyClass have a fully accessible property ClassProperties. To that object, it would look exactly like a Properties object, but behind the scenes, MyClass is actually computing and modifying the results of the fields. This method of declaration is obviously wrong since I can't access GetActualName() and SetActualName() from within the SubProperties definition. How would I achieve something like this?
Are you looking for something like this?
abstract class Properties
{
public abstract string Name { get; set; }
}
class MyClass
{
private class SubProperties : Properties
{
private MyClass myClass;
public SubProperties(MyClass myClass)
{
this.myClass = myClass;
}
public override Name
{
get { return this.myClass.GetActualName(); }
set { this.myClass.SetActualName(value); }
}
}
private string name;
public MyClass
{
this.MyClassProperties = new SubProperties(this);
}
public Properties MyClassProperties { get; private set; }
private string GetActualName()
{
return this.name;
}
private void SetActualName(string s)
{
this.name = s;
}
}
You need to pass a reference to a MyClass instance to the SubProperties instance if you want to access MyClass methods from SubProperties.
public virtual string Name { get; set; }