Amin
Amin

Reputation: 1

Type Of Object In C#

(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

Answers (7)

xanatos
xanatos

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

Jay
Jay

Reputation: 57899

Yes, there is!

There are two options here.

  1. If the logic of SaveObject() is the same for all three classes
  2. If the logic is different

In 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

Gabe
Gabe

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

vcsjones
vcsjones

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

Michael Petrotta
Michael Petrotta

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

Dima
Dima

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

Luke Baulch
Luke Baulch

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

Related Questions