public class Base {...}
public class Complex: Base {...}
public class MyOtherClass<T> {...}
以及这两种类型的列表
List<MyOtherClass<Complex>> listOfComplex
List<MyOtherClass<Base>> listOfBase
我想要一个列表
listOfComplex.Union(listOfBase)
但是我无法将一种类型的泛型转换为另一种类型的泛型,即使Complex是从Base派生的 有一个基类列表的可能性吗?
答案 0 :(得分:3)
尽管Complex
源自Base
,但MyOtherClass<Complex>
和MyOtherClass<Base>
之间没有没有这种关系。这就是为什么您不能在两个列表中创建一个Union
的原因。对于框架这两种通用类型完全不同。
现在的解决方案实际上取决于您的班级到底做什么。在Docs中查看协方差和逆方差的主题-这是两种特殊情况,如果类型仅是输入或输出,则可以在两个通用类型之间创建转换。
您还可以在执行“联合”操作之前添加自定义类型转换或将项目手动转换为“基本”类型。
答案 1 :(得分:1)
由于Covariance and Contravariance in Generics的工作方式,尤其是invariance
,这意味着您只能使用最初指定的类型;因此不变的泛型类型参数既不是协变也不是协变。
您不能将List<Base>
的实例分配给类型为List<Complex>
或相反的变量。自定义通用类也是如此。编译器不能使用隐式转换来转换类型。
即使添加通用类型约束。 A<B>
和A<C>
是两种不同的类型,即使C
是从B
继承而来的,它们之间也没有转换(因为AC
不是从{{1}继承而来的) })
答案 2 :(得分:0)
您应该在您的泛型中指定T是基于Type的类:
<?php
$clientName = "";
$squareFeet = 0;
$capRate = 0;
$utilityBillSavings = 0;
$cashPayments = 0;
$prodVal = 0;
if(isset($_POST["clientName"]) && isset($_POST['squareFeet']) && isset($_POST['capRate']) && isset($_POST['utilityBillSavings']) && isset($_POST['cashPayments'])) {
$clientName = $_POST['clientName']; echo $clientName . "<br>";
$squareFeet = $_POST['squareFeet']; echo $squareFeet . "<br>";
$capRate = $_POST['capRate']; echo $capRate . "<br>";
$utilityBillSavings = $_POST['utilityBillSavings']; echo $utilityBillSavings . "<br>";
$cashPayments = $_POST['cashPayments']; echo $cashPayments . "<br>";
$capRate = $capRate / 100;
$propVal = (($utilityBillSavings/$squareFeet)/$capRate)*$squareFeet;
echo "Property Value Increase is: " . $propVal . "<br>";
}
?>
<html><head><body>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" name="form" id="form">
<div>Client name</div><div><input type="text" name="clientName" size="20"></div>
<div>Sq Ft</div><div><input type="number" name="squareFeet" min="0" max="1000000000000"></div>
<div>Cap Rate</div><div><input type="number" name="capRate" min="0" max="1000000000000"></div>
<div>Bill Savings</div><div><input type="number" name="utilityBillSavings" min="0" max="1000000000000"></div>
<div>Cash Payment</div><div><input type="number" name="cashPayments" min="0" max="1000000000000"></div>
<div><input type="button" name="submit" value=" Calculate Increase In Property Value "></div>
</form>
</body></html>
仅当从Base And Union派生的T应该起作用时,T才会被接受
由于@Marie,这里有一些有关泛型的文档:
答案 3 :(得分:0)
@MartinZikmund解释了为什么它不起作用。解决此类问题的方法是从非泛型基类派生泛型类,或者让它们实现公共接口。
public class MyOtherClassBase { }
public class MyOtherClass<T> : MyOtherClassBase { }
然后,您可以显式指定MyOtherClassBase
作为Union
的通用参数。现在,Union
将期望输入IEnumerable<MyOtherClassBase>
类型。类型List<MyOtherClass<T>>
的列表与IEnumerable<MyOtherClassBase>
兼容。
var result = listOfComplex.Union<MyOtherClassBase>(listOfBase);
请注意声明中的out
关键字
public interface IEnumerable<out T> : System.Collections.IEnumerable
它使接口协变。另请参阅问题<out T> vs <T> in Generics,尤其是里德·科普西(Reed Copsey)的answer。