Reputation: 1
(Excuse me, my English language is bad) I have three classes in c#,all of them have a method "SaveObject", in GUI I want to call these methods,So i write this code:
private void save(object sender, EventArgs e)
{
switch(sender.GetType().Name.Tostring())
{
case "ClassOne" :
ClassOne obj1 = sender as ClassOne;
obj1.SaveObject();
break;
case "ClassTwo" :
ClassTwo obj2 = sender as ClassTwo;
obj2.SaveObject();
break;
case "ClassThree" :
ClassThree obj3 = sender as ClassThree;
obj3.SaveObject();
break;
}
}
is there any way to write this code better than above;
Upvotes: 0
Views: 272
Reputation: 111830
You should have the three classes inherit my an interface
(IMyInterface
) with a method SaveObject
, and then cast sender
to IMyInterface
and from there call SaveObject()
.
I'll add that C# has the is
operator.
if (sender is ClassOne)
but then you can't use the switch.
Ah and Name
already is a string
, so you don't need a ToString
Upvotes: 1
Reputation: 57899
Yes, there is!
There are two options here.
SaveObject()
is the same for all three classesIn the first case, you create what is called an abstract class, and the other classes "inherit" it. This means that the SaveObject
method is create once, and you don't have to write it in all three classes.
public abstract class ClassBase
{
public void SaveObject()
{
// save logic goes here
}
}
public class ClassOne : ClassBase
{
// other methods and properties; do the same for ClassTwo and ClassThree
}
Now you can do this in your event handler:
if (sender is ClassBase)
{
((ClassBase) sender).SaveObject();
}
In the second case, where the logic is different among all three classes, you create an "interface" and your other classes will "implement" it. This means that they each MUST declare their own SaveObject()
method.
public interface IClass
{
void SaveObject(); // use the signature only here -- no logic; you cannot use access modifiers like "public"
}
public class ClassOne : IClass
{
// other stuff
public void SaveObject()
{
// save logic for this class
}
}
public class ClassTwo : IClass
{
// other stuff
public void SaveObject()
{
// different save logic for this class
}
}
Now you can create methods like this:
public void PerformSave(IClass myClass)
{
myClass.SaveObject();
}
…and it will work whether you pass in an instance of ClassOne
, ClassTwo
or ClassThree
.
In your case, however, you just have an argument of type object
. You can do this:
private void save(object sender, EventArgs e)
{
if(sender is IClass)
{
((IClass) sender).SaveObject();
}
}
Upvotes: 1
Reputation: 86708
If you can't create an interface (perhaps because you have no control over the classes) and are using C# 4, you can use the new dynamic capabilities:
((dynamic)sender).SaveObject();
If you can't create an interface and can't use dynamic
, you will have to use Reflection.
Upvotes: 1
Reputation: 141598
Sure. The problem with your code is it will break if you rename a class by doing any kind of refactoring. I would write it as:
private void save(object sender, EventArgs e)
{
if (sender is ClassOne)
{
((ClassOne)sender).SaveObject();
}
else if (sender is ClassTwo)
{
((ClassTwo)sender).SaveObject();
}
else if (sender is ClassThree)
{
((ClassThree)sender).SaveObject();
}
else
{
throw new Exception("Unknown type");
}
}
An interface might be a better solution though. Why not just put an interface on all of the classes with a member called SaveObject
, and just case it to the interface?
public class ClassOne : IPersistable
{
}
public class ClassTwo : IPersistable
{
}
//etc...
public interface IPersistable
{
void SaveObject();
}
Then:
var persistable = (IPersistable)sender;
persistable.SaveObject();
Upvotes: 0
Reputation: 60902
Have all three classes implement a single interface: ISaveable
, or something. Add a single method to that interface: SaveObject
, and implement that method in each of the three classes (which you really already have).
Then you can replace the above with this:
private void save(object sender, EventArgs e)
{
ISaveable saveable = (ISaveable)sender;
saveable.SaveObject();
}
Upvotes: 4
Reputation: 6741
It's better to expose common interface with method SaveObject() for all 3 classes, then cast your sender to that interface and call method.
Or you can take a look on Strategy/Command patterns.
Upvotes: 0
Reputation: 3656
I recommend you implement an interface with the 'SaveObject()' method and inherit this interface for each of your classes. Then you can just perform a cast and call the method.
public interface ISaveObject
{
void SaveObject();
}
public class ClassOne : ISaveObject
{
public void SaveObject()
{
//...
}
}
Upvotes: 0