将通用输入对象传递给方法 C#

Gee*_*nja 4 c# generics

我有一个方法 ABC(),它从我的应用程序中的两个不同位置调用。从这两个地方我都有不同的类对象,这些对象实现了通用接口“IDestination”。

我的两个类和接口如下所示:

public class ClassA: IDestination
{
        public string Var1 { get; set; }    
        public string Var2 { get; set; }    
        public string Var3 { get; set; }
}

public class ClassB: IDestination
{
        public string Var1 { get; set; }
        public string Var2 { get; set; }
        public string Var3 { get; set; }
        public string Var4 { get; set; }
        public string Var5 { get; set; }
}

public interface IDestination
{
        string Var1 { get; set; }
        string Var2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

截至目前,方法 ABC() 接受 classA 的对象,我希望它也可以接受 classB 的对象。为此,我将方法定义设为通用,如下所示:

public string ABC<T>(T obj)
{

}
Run Code Online (Sandbox Code Playgroud)

但是,问题出在 ABC 方法内部,我想访问类的属性(classA 和 classB 都是)。

public string ABC<T>(T obj)
 {
        //Some code
        obj.var2; //of classA

        obj.var4; //of classB
        //Some code
 }
Run Code Online (Sandbox Code Playgroud)

而且我不允许对界面进行任何更改。

我怎样才能实现这个目标?我不想创建另一种方法来处理不同的类对象。任何想法?

Mat*_*zer 5

首先,接口不是继承的,而是实现的

另一方面,通用参数可以受到约束:

public string ABC<T>(T obj) where T : IDestination
Run Code Online (Sandbox Code Playgroud)

OP 说:

而且我不允许对界面进行任何更改。

顺便说一句,根据您的要求和泛型类型约束,您将无法同时接受两者classAclassB因为 C# 不支持多重继承。如果您想访问classB成员,您需要扩展您的IDestination接口以定义您想要访问的所有属性,类型classBIDestination

public interface IDestination
{
      string Var1 { get; set; }
      string Var2 { get; set; }
      string Var3 { get; set; }
      string Var4 { get; set; }
      string Var5 { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用其余属性定义第二个接口:

public interface IDestination2
{
      string Var3 { get; set; }
      string Var4 { get; set; }
      string Var5 { get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

...您将在以下位置实现它classB

public class ClassB: IDestination, IDestination2
Run Code Online (Sandbox Code Playgroud)

不管怎样,这里的问题是你不能限制泛型参数接受某些给定类的两种不同的继承。也就是说,例如,如果您限制TIDestinationIDestination2,您将无法ClassA作为参数给出,因为它没有实现IDestination2

OP 说:

我不想创建另一种方法来处理不同的类对象。

实际上,这也可以在没有泛型的情况下通过方法重载来解决,即使您不想走这条路,这也不是一种邪恶的方法:

public void ABC(IDestination destination) {}
public void ABC(IDestination2 destination) {}

// or directly...

public void ABC(ClassA destination) {}
public void ABC(ClassB destination) {}
Run Code Online (Sandbox Code Playgroud)

否则,您需要按如下方式实现:

public string ABC<T>(T obj) where T : IDestination
{
     ClassA a = obj as ClassA;
     ClassB b = obj as ClassB;

     // Now if you want to access Var1, Var2 you can access them
     // using "obj" reference, because T is IDestination
     string var1 = obj.Var1;
     string var2 = obj.Var2;

     if(a != null) 
     {
         // Here access all ClassA members...
     }

     if(b != null)
     {
         // Here access all ClassB members...
     }
}
Run Code Online (Sandbox Code Playgroud)

对我来说,上述方法是一个设计缺陷。如果我使用泛型类型和接口,是因为我想使用等于泛型类型参数类型的对象。

如果我开始对接口的特定实现执行向下转换IDestination,这就像违背了使用的目的,并且您的方法似乎可能只是接受object,因为您的方法将访问ClassAandClassB成员而不是IDestination成员:

public string ABC(object obj)
{
     ClassA a = obj as ClassA;
     ClassB b = obj as ClassB;

     // Now if you want to access Var1, Var2 you can access them
     // using "obj" reference, because T is IDestination
     string var1 = obj.Var1;
     string var2 = obj.Var2;

     if(a != null) 
     {
         // Here access all ClassA members...
     }

     if(b != null)
     {
         // Here access all ClassB members...
     }

     return "";
}
Run Code Online (Sandbox Code Playgroud)

长话短说

总之,您应该使用接口来键入对象和通用约束,以保证引用的键入最少,以避免强制转换。否则,通用类型不是您的解决方案。