简体   繁体   English

C#:传递通用对象

[英]C# : Passing a Generic Object

I want to have a generic print function...PrintGeneric(T)...in the following case, what am I missing? 我希望有一个通用的打印功能... PrintGeneric(T)......在下面的例子中,我缺少什么?

As always your help/insight is appreciated... 一如既往,感谢您的帮助/见解......

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.GetType()>(test2);
    }

    // following doesn't compile
    public void PrintGeneric<T>(T test)
    {
        Console.WriteLine("Generic : " + test.myvar);
    }
}

It doesn't compile because T could be anything, and not everything will have the myvar field. 它不能编译,因为T可以是任何东西,并不是所有东西都有myvar字段。

You could make myvar a property on ITest : 你可以让myvar成为ITest一个属性:

public ITest
{
    string myvar{get;}
}

and implement it on the classes as a property: 并在类作为属性实现它:

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

and then put a generic constraint on your method: 然后对您的方法设置一个通用约束:

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

but in that case to be honest you are better off just passing in an ITest: 但在这种情况下,说实话,你最好只是传递一个ITest:

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

You're missing at least a couple of things: 你至少缺少一些东西:

  • Unless you're using reflection, the type arguments need to be known at compile-time, so you can't use 除非您使用反射,否则需要在编译时知道类型参数,因此您无法使用

     PrintGeneric<test2.GetType()> 

    ... although in this case you don't need to anyway ......虽然在这种情况下你无论如何都不需要

  • PrintGeneric doesn't know anything about T at the moment, so the compiler can't find a member called T PrintGeneric目前对T PrintGeneric ,因此编译器找不到名为T的成员

Options: 选项:

  • Put a property in the ITest interface, and change PrintGeneric to constrain T : 将属性放在ITest界面中,并更改PrintGeneric以约束T

     public void PrintGeneric<T>(T test) where T : ITest { Console.WriteLine("Generic : " + test.PropertyFromInterface); } 
  • Put a property in the ITest interface and remove the generics entirely: 将属性放在ITest界面中并完全删除泛型:

     public void PrintGeneric(ITest test) { Console.WriteLine("Property : " + test.PropertyFromInterface); } 
  • Use dynamic typing instead of generics if you're using C# 4 如果您使用的是C#4,请使用动态类型而不是泛型

In your generic method, T is just a placeholder for a type. 在通用方法中, T只是一个类型的占位符。 However, the compiler doesn't per se know anything about the concrete type(s) being used runtime, so it can't assume that they will have a var member. 但是,编译器本身并不了解运行时使用的具体类型,因此不能假设它们将具有var成员。

The usual way to circumvent this is to add a generic type constraint to your method declaration to ensure that the types used implement a specific interface (in your case, it could be ITest ): 避免这种情况的常用方法是在方法声明中添加泛型类型约束,以确保使用的类型实现特定的接口(在您的情况下,它可能是ITest ):

public void PrintGeneric<T>(T test) where T : ITest

Then, the members of that interface would be directly available inside the method. 然后,该接口的成员将直接在该方法中可用。 However, your ITest is currently empty, you need to declare common stuff there in order to enable its usage within the method. 但是,您的ITest当前是空的,您需要在那里声明常用的东西,以便在方法中使用它。

You'll have to provide more information about the generic type T . 您必须提供有关泛型类型T更多信息。 In your current PrintGeneric method, T might as well be a string , which does not have a var member. 在当前的PrintGeneric方法中, T也可能是一个string ,它没有var成员。

You may want to change var to a property rather than a field 您可能希望将var更改为属性而不是字段

public interface ITest
{
    string var { get; }
}

And add a constraint where T: ITest to the PrintGeneric method. 并添加一个约束where T: ITestPrintGeneric方法。

You need to define something in the interface, such as: 您需要在界面中定义一些内容,例如:

public interface ITest
{
    string Name { get; }
}

Implement ITest in your classes: 在您的课程中实施ITest

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

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

Then restrict your generic Print function, to ITest : 然后将您的通用Print功能限制为ITest

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

try 尝试

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

as @Ash Burlaczenko has said you cant name a variable after a keyword, if you reallllly want this prefix with @ symbol to escape the keyword 正如@Ash Burlaczenko所说,你不能在一个关键字之后命名一个变量,如果你真的希望这个带有@符号的前缀来逃避关键字

You cannot access var with the generic. 您无法使用泛型访问var

Try something like 尝试类似的东西

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

And override ToString method [1] 并覆盖ToString方法[1]

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM