在泛型方法中返回特定类型

本文关键字:类型 返回 泛型方法 | 更新日期: 2023-09-27 18:32:15

我写了以下方法:

public T CreatePackage<T>() where T : new()
{
        var package = new T();
        if (typeof(ComponentInformationPackage) == typeof(T))
        {
            var compInfoPackage = package as ComponentInformationPackage;
            // ...
            return compInfoPackage;
        }
        throw new System.NotImplementedException();
}

我检查 T 是什么类型,并根据此处理我的变量。当我想返回它时,我收到编译器错误。

"组件信息包类型不能隐式转换为 T"

如何解决这个问题?

在泛型方法中返回特定类型

首先:在强制转换不起作用的情况下,安全的强制转换确实有效:

return CompInfoPackage as T;

。前提是对Tclass约束:

public static T CreatePackage<T>() where T : class, new() { ... }

第二:给定此代码:

var package = new T();
if (typeof(ComponentInformationPackage) == typeof(T))
{
    var compInfoPackage = package as ComponentInformationPackage;
    // ...
    return (T)compInfoPackage; 
}

。您已经具有对新对象的引用package。由于它是 T 型,编译器已经喜欢它作为返回类型。为什么不归还呢?

var package = new T();
if (typeof(ComponentInformationPackage) == typeof(T))
{
    var compInfoPackage = package as ComponentInformationPackage;
    // ...
    return package; // Same object as compInfoPackage
}

您必须强制转换为T,因为您的方法返回T的实例而不是ComponentInformationPackage

return (T)CompInfoPackage;

编译器没有机会知道T实际上是一个ComponentInformationPackage。但是,正如您在此强制转换之前已经检查过的那样,它可能永远不会失败。

但是,我不确定为什么您有一个泛型类型,因为您的方法只处理ComponentInformationPackage的实例。省略类型参数和约束,只需返回您已经执行的操作。

编辑:我已经在注释中提到过,您也可以返回package(没有任何强制转换),因为编译器已经知道packageT的实例。你最后的机会是return (T)(object) CompInfoPackage,但对我来说似乎很奇怪。

投射回T不会像HimBromBeere建议的那样工作,因此不是你的解决方案。为了使编译器接受强制转换,您将需要一个额外的类型约束 ComponentInformationPackage 。所以这将是你的修复:

public T CreatePackage<T>()
    where T : ComponentInformationPackage, new()
{
        var package = new T();
        if (typeof(ComponentInformationPackage) == typeof(T))
        {
            var compInfoPackage = package as ComponentInformationPackage;
            // ...
            return (T)compInfoPackage;
        }
        throw new System.NotImplementedException();
}

此外,我建议使用大写约定作为MSDN的指南。这与您的问题无关,但这是一个提示。

如果你想根据类型处理对象的创建,你不应该在这里使用泛型(因为它不是泛型)。也许使用工厂模式来实现这一点。

我认为你试图实现的泛型是不可能的,除非你让所有类型都实现通用接口或属于一些常见的抽象类型

public T CreatePackage<T>()
    where T : IPackage, new()
{
        var package = new T();
        if (typeof(ComponentInformationPackage) == typeof(T))
        {
            var compInfoPackage = package as ComponentInformationPackage;
            // ...
            return (T)compInfoPackage;
        }
        throw new System.NotImplementedException();
}

在上面的例子中,你所有的类都应该实现IPackage接口。

似乎您想根据传递的类型创建实例...你需要像工厂模式这样的东西。我认为你应该重新考虑你的设计