Roo*_*ian 7 .net c# generics exception-handling
public class ConfigControlBase<T> : UserControl
where T : ProviderBase
{
public T Provider { get; set; }
public void Init(T provider)
{
this.Provider = provider;
}
}
public abstract class ProviderBase
{
public abstract ConfigControlBase<ProviderBase> GetControl();
}
public class ProviderXConfigControl : ConfigControlBase<ProviderX>
{
}
public class ProviderX : ProviderBase
{
public override ConfigControlBase<ProviderBase> GetControl()
{
var confControl = new ProviderXConfigControl() as ConfigControlBase<ProviderX>;
return confControl;
}
}
Run Code Online (Sandbox Code Playgroud)
return confControl; 抛出异常:
无法隐式转换
ConfigControlBase<ProviderX>为ConfigControlBase<ProviderBase>
Eri*_*ert 21
让我们更改类和属性的名称,但保持形状相同:
public class Cage<T> where T : Animal
{
public T Contents { get; set; }
}
public class Aquarium : Cage<Fish> { }
public abstract class Animal
{
public abstract Cage<Animal> GetCage();
}
public class Fish : Animal
{
public override Cage<Animal> GetCage()
{
return (Cage<Animal>)(new Aquarium());
}
}
Run Code Online (Sandbox Code Playgroud)
现在很清楚为什么这不合法?假设它是合法的.然后你可以这样做:
Fish fish = new Fish();
Cage<Animal> cage = fish.GetCage();
cage.contents = new Tiger();
Run Code Online (Sandbox Code Playgroud)
现在你的水族馆里有一只老虎.没有人想要那样.
编译器(或运行时)必须以某种方式防止此类型错误; 它选择尽快防止它.它最早可以做的是从水族馆转换到的类型测试Cage<Animal>.编译器知道这最终会导致水族箱中的老虎,所以它根本不允许转换.如果强制编译器通过强制转换允许它,那么它会在运行时失败.
具有可分配类型参数的泛型类型本身不可分配.
举例来说,你不能施放List<string>到List<object>,虽然string是一个object.
为什么不支持这样的铸造并不是很明显,所以让我举个例子:
var words = new List<string> { "Serve God", "love me", "mend" };
var objects = (List<object>) words; // C# compiler wouldn't allow this
objects.Add (new Car()); // we just added a Car to Shakespeare's work and the universe exploded
Run Code Online (Sandbox Code Playgroud)
C#并不鼓励宇宙爆炸,但是自C#4.0以来,这个想法的一个轻量级版本已经实现.你知道,在某些情况下,这种铸造实际上是安全的.
.NET 4.0 仅为接口和委托带来了泛型中协方差和逆变的概念,您可能需要查看它.
示例(在.NET 4.0之前不起作用):
void HandleCollection (IEnumerable<object> collection)
{
// ...
}
var words = new List<string> { "Serve God", "love me", "mend" };
// IEnumerable is defined as IEnumerable<out T> in .NET 4.0
// 'out' keyword guarantees that T is only used for return values
// and therefore client code can't explode the universe
var objects = (IEnumerable<object>) words;
HandleCollection (objects);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
479 次 |
| 最近记录: |