• 欢迎访问,如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

约束的疑惑

.Net技术 码拜 3年前 (2017-04-25) 246次浏览
为什么本人标红的地方没报错,U和T又没继承关系(又没关联),怎么能通过呢,就好比本人标蓝地方的注释
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace delete2
{
public class Farm<T> : IEnumerable<T>
where T : Animal
{
private List<T> animals = new List<T>();
public List<T> Animals
{
get
{
return animals;
}
}
public IEnumerator<T> GetEnumerator()
{
return animals.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return animals.GetEnumerator();
}
public void MakeNoises()
{
foreach (T animal in animals)
{
animal.MakeANoise();
}
}
public void FeedTheAnimals()
{
foreach (T animal in animals)
{
animal.Feed();
}
}
public Farm<Cow> GetCows()
{
Farm<Cow> cowFarm = new Farm<Cow>();
foreach (T animal in animals)
{
if (animal is Cow)
{
cowFarm.Animals.Add(animal as Cow);
}
}
return cowFarm;
}
public static implicit operator List<Animal>(Farm<T> farm)
{
List<Animal> result = new List<Animal>();
foreach (T animal in farm)
{
result.Add(animal);
}
return result;
}
public static Farm<T> operator +(List<T> farm1, Farm<T> farm2)
{
Farm<T> result = new Farm<T>();
foreach (T animal in farm2)
{
result.Animals.Add(animal);
}
foreach (T animal in farm1)
{
if (!result.Animals.Contains(animal))
{
result.Animals.Add(animal);
}
}
return result;
}
public static Farm<T> operator +(Farm<T> farm1, List<T> farm2)
{
return farm2 + farm1;
}
public static Farm<T> operator +(Farm<T> farm1, Farm<T> farm2)
{
Farm<T> result = new Farm<T>();
foreach (T animal in farm1)
{
result.Animals.Add(animal);
}
foreach (T animal in farm2)
{
if (!result.Animals.Contains(animal))
{
result.Animals.Add(animal);
}
}
return result;
}
public static implicit operator Farm<Animal>(Farm<T> farm)
{
Farm<Animal> result = new Farm<Animal>();
foreach (T animal in farm)
{
result.Animals.Add(animal);
}
return result;
}
public Farm<U> GetSpecies<U>() where U :T
{
Farm<U> speciesFarm = new Farm<U>();
foreach (T animal in animals)
{
if ((animal as Cow) is U)
{
Console.WriteLine(animal as Cow); //假如把这句代码改成这样就行不通了Console.WriteLine((Cow)animal);原因本人知道就是下面一行代码的原理

speciesFarm.Animals.Add((U)(T)animal);
}
}
return speciesFarm;
}
}
public class SuperCow : Cow
{
public void Fly()
{
Console.WriteLine(“{0} is flying!”, name);
}
public SuperCow(string newName)
: base(newName)
{ }
public override void MakeANoise()
{
Console.WriteLine(“{0} says “here I come to save the day!””, name);
}
}
public class Cow : Animal
{
public void Milk()
{
Console.WriteLine(“{0} has been milked.”, name);
}
public Cow(string newName)
: base(newName)
{ }
public override void MakeANoise()
{
Console.WriteLine(“{0} says “moo!””, name);
}
}
public class Chicken : Animal
{
public void LayEgg()
{
Console.WriteLine(“{0} has laid an egg.”, name);
}
public Chicken(string newName)
: base(newName)
{
}
public override void MakeANoise()
{
Console.WriteLine(“{0} says “cluck!”;”, name);
}
}
public abstract class Animal
{
protected string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public Animal()
{
name = “The animal with no name”;
}
public Animal(string newName)
{
name = newName;
}
public void Feed()
{
Console.WriteLine(“{0} has been fed.”, name);
}
public abstract void MakeANoise();
}

class Program
{
static void Main(string[] args)
{
Farm<Animal> farm = new Farm<Animal>();
farm.Animals.Add(new Cow(“Jack”));
farm.Animals.Add(new Chicken(“Vera”));
farm.Animals.Add(new Chicken(“Sally”));
farm.Animals.Add(new SuperCow(“Kevin”));
farm.MakeNoises();
Farm<Cow> dairyFarm = farm.GetCows();
dairyFarm.FeedTheAnimals();
foreach (Cow cow in dairyFarm)
{
if (cow is SuperCow)
{
(cow as SuperCow).Fly();
}
}
Farm<Animal> newFarm =dairyFarm+ farm  ;
Farm<Animal> a = new Farm<Animal>();
a=farm.GetSpecies<Cow>();
foreach (Cow x in a)
Console.WriteLine(x.Name);
Console.ReadKey();
}
}
}

解决方案

39

speciesFarm.Animals.Add((U)(T)animal);
只需写作
speciesFarm.Animals.Add((U)animal);
由于
public Farm<U> GetSpecies<U>() where U :T
传入的 U 类型是被当作做 T 类型处理的
Console.WriteLine(animal as Cow);
Console.WriteLine((Cow)animal);
不同之处在于 animal as Cow 是可空的,即转换允许失败
而 (Cow)animal 就不是这样,用于编译器依据代码,无法从 T 推导出 Cow,所以会报错(虽然 animal 实际就是 Cow 类型)

1

虽然编译通过,但假如转换不成功,会在运行时报运行时错误的

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明约束的疑惑
喜欢 (0)
[1034331897@qq.com]
分享 (0)