C#中的对象类型

时间:2011-09-06 05:09:21

标签: c#

(打扰一下,我的英语很差) 我在c#中有三个类,它们都有一个方法“SaveObject”, 在GUI我想调用这些方法,所以我写这段代码:

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;
   }
}

有没有办法比上面更好地编写这段代码;

7 个答案:

答案 0 :(得分:4)

让所有三个类都实现一个接口:ISaveable或其他东西。向该接口添加一个方法:SaveObject,并在三个类中的每个类中实现该方法(您实际已经拥有)。

然后你可以用以下代码替换上面的内容:

private void save(object sender, EventArgs e)
{
    ISaveable saveable = (ISaveable)sender;
    saveable.SaveObject();
}

答案 1 :(得分:1)

您应该让这三个类使用方法interface继承我的IMyInterfaceSaveObject),然后将sender转换为IMyInterface并从那里开始致电SaveObject()

我将补充说C#有is运算符。

if (sender is ClassOne)

但是你不能使用开关。

啊,Name已经是string,因此您不需要ToString

答案 2 :(得分:1)

如果您无法创建界面(可能是因为您无法控制类)并且正在使用C#4,则可以使用新的动态功能:

((dynamic)sender).SaveObject();

如果您无法创建界面而无法使用dynamic,则必须使用反射。

答案 3 :(得分:1)

是的,有!

这里有两种选择。

  1. 如果SaveObject()的逻辑对于所有三个类都相同
  2. 如果逻辑不同
  3. 在第一种情况下,您创建所谓的抽象类,其他类“继承”它。这意味着SaveObject方法只创建一次,您不必在所有三个类中编写它。

    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
    }
    

    现在您可以在事件处理程序中执行此操作:

    if (sender is ClassBase)
    {
        ((ClassBase) sender).SaveObject();
    }
    

    在第二种情况下,所有三个类的逻辑都不同,你创建一个“接口”,其他类将“实现”它。这意味着他们每个人都必须声明自己的SaveObject()方法。

    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
        }
    }
    

    现在你可以创建这样的方法:

    public void PerformSave(IClass myClass)
    {
        myClass.SaveObject();
    }
    

    ...无论您是否传递ClassOneClassTwoClassThree的实例,它都会有效。

    但是,在您的情况下,您只有object类型的参数。你可以这样做:

    private void save(object sender, EventArgs e)
    {
        if(sender is IClass)
        {
            ((IClass) sender).SaveObject();
        }
    }
    

答案 4 :(得分:0)

我建议您使用'SaveObject()'方法实现一个接口,并为每个类继承此接口。然后你可以执行演员表并调用方法。

public interface ISaveObject
{
    void SaveObject();
}

public class ClassOne : ISaveObject
{
    public void SaveObject()
    {
        //...
    }
}

答案 5 :(得分:0)

最好使用方法SaveObject()为所有3个类公开公共接口,然后将发送方转换为该接口并调用方法。
或者您可以查看策略/命令模式。

答案 6 :(得分:0)

不确定。代码的问题是,如果通过进行任何重构来重命名类,它将会中断。我会把它写成:

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");
   }
}

虽然界面可能是更好的解决方案。为什么不在一个名为SaveObject的成员的所有类上添加一个接口,只是将它放到接口上?

public class ClassOne : IPersistable
{
}

public class ClassTwo : IPersistable
{
}

//etc...

public interface IPersistable
{
    void SaveObject();
}

然后:

var persistable = (IPersistable)sender;
persistable.SaveObject();