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: ITest
为PrintGeneric
方法。
在通用方法中, 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"; } } }
然后将您的通用Print
function限制为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所说,你不能在一个关键字之后命名一个变量,如果你真的希望这个带有@符号的前缀来逃避关键字