C#:传递通用对象

我想要一个通用的打印function… PrintGeneric(T)…在下面的例子中,我缺少什么?

一如既往地感谢您的帮助/见解……

public interface ITest {} public class MyClass1 : ITest { public string myvar = "hello 1"; } public class MyClass2 : ITest { public string myvar = "hello 2"; } class DoSomethingClass { static void Main() { MyClass1 test1 = new MyClass1(); MyClass2 test2 = new MyClass2(); Console.WriteLine(test1.myvar); Console.WriteLine(test2.myvar); Console.WriteLine(test1.GetType()); PrintGeneric(test1); PrintGeneric(test2); } // following doesn't compile public void PrintGeneric(T test) { Console.WriteLine("Generic : " + test.myvar); } } 

它没有编译,因为T可以是任何东西,并不是所有东西都有myvar字段。

你可以让myvar成为ITest一个属性:

 public ITest { string myvar{get;} } 

并在类作为属性实现它:

 public class MyClass1 : ITest { public string myvar{ get { return "hello 1"; } } } 

然后对您的方法设置一个通用约束:

 public void PrintGeneric(T test) where T : ITest { Console.WriteLine("Generic : " + test.myvar); } 

但在这种情况下,说实话,你最好只是传递一个ITest:

 public void PrintGeneric(ITest test) { Console.WriteLine("Generic : " + test.myvar); } 

你至少缺少一些东西:

  • 除非您使用reflection,否则需要在编译时知道类型参数,因此您无法使用

     PrintGeneric 

    …虽然在这种情况下你无论如何都不需要

  • PrintGeneric目前对T PrintGeneric ,因此编译器找不到名为T的成员

选项:

  • 将属性放在ITest界面中,并更改PrintGeneric以约束T

     public void PrintGeneric(T test) where T : ITest { Console.WriteLine("Generic : " + test.PropertyFromInterface); } 
  • 将属性放在ITest界面中并完全删除generics:

     public void PrintGeneric(ITest test) { Console.WriteLine("Property : " + test.PropertyFromInterface); } 
  • 如果您使用的是C#4,请使用动态类型而不是generics

您必须提供有关generics类型T更多信息。 在当前的PrintGeneric方法中, T也可能是一个string ,它没有var成员。

您可能希望将var更改为属性而不是字段

 public interface ITest { string var { get; } } 

并添加一个约束where T: ITestPrintGeneric方法。

在通用方法中, T只是一个类型的占位符。 但是,编译器本身并不了解运行时使用的具体类型,因此不能假设它们将具有var成员。

避免这种情况的常用方法是在方法声明中添加generics类型约束,以确保使用的类型实现特定的接口(在您的情况下,它可能是ITest ):

 public void PrintGeneric(T test) where T : ITest 

然后,该接口的成员将直接在该方法中可用。 但是,您的ITest当前是空的,您需要在那里声明常用的东西,以便在方法中使用它。

您需要在界面中定义一些内容,例如:

 public interface ITest { string Name { get; } } 

在您的课程中实施ITest

 public class MyClass1 : ITest { public string Name { get { return "Test1"; } } } public class MyClass2 : ITest { public string Name { get { return "Test2"; } } } 

然后将您的通用Printfunction限制为ITest

 public void Print(T test) where T : ITest { } 

您无法使用generics访问var

尝试类似的东西

 Console.WriteLine("Generic : {0}", test); 

并覆盖ToString方法[1]

[1] http://msdn.microsoft.com/en-us/library/system.object.tostring.aspx

尝试

 public void PrintGeneric(T test) where T: ITest { Console.WriteLine("Generic : " + test.@var); } 

正如@Ash Burlaczenko所说,你不能在一个关键字之后命名一个变量,如果你真的希望这个带有@符号的前缀来逃避关键字