我有一个接口,该接口由存储了更多信息的更多类实现。而且我需要能够转换实现,而不必明确地说这是一个实现。
public interface IAnimal
{
string Name { get; set; }
Type GetType();
}
public class Dog : IAnimal
{
public string Name { get; set; }
Type GetType() {return typeof(Dog);}
public int TimesBarked { get; set; }
}
public class Rhino : IAnimal
{
public string Name { get; set; }
Type GetType() {return typeof(Rhino);}
public bool HasHorn { get; set; }
}
在大多数代码中,我毫无问题地使用该接口,但是在某些时候,我需要将实现强制转换为其原始类型。
IAnimal animal = new Dog
{
Name = "Ben",
TimesBarked = 30
}
// Doing stuff with Ben
// In some other function
AnotherObject.SomeMethodThatNeedsToKnowType(animal) //Needs to be Converted before putting here
我不知道会得到哪个对象,所以我必须做一些可以将任何东西转换成原始类型的东西。
不幸的是,Convert.ChangeType(animal, animal.GetType())
返回object{Dog}
而不是Dog
。我可以更改接口及其实现,但不能更改Method。
答案 0 :(得分:5)
我不知道我会得到哪个对象,所以我不得不做些可以将任何东西转换为原始类型的东西。
那您打算怎么做 ?由于您不知道类型,因此您不知道可以调用什么方法,等等。这就是为什么原始解决方案返回object
的原因。
您可以使用dynamic
,但如果尝试使用不存在的方法,则会抛出该错误。最接近的结果就是简单的is
检查(为简便起见,使用C#7模式匹配):
if (animal is Dog dog)
//Do stuff with dog
else if (animal is Rhino rhino)
// Do stuff with rhino
重大免责声明:垂头丧气是一个巨大的危险信号。当您什至不知道期望哪种类型时,向下转换就更糟了。您的设计几乎肯定需要重新考虑。
答案 1 :(得分:1)
不确定,您的最终结局是什么。如果您不想使用IS和AS,我可能会...不管怎样:
using System;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public interface IAnimal
{
string Name { get; set; }
//Type GetType();
}
public class Dog : IAnimal
{
public string Name { get; set; }
//new Type GetType() { return typeof(Dog); }
public int TimesBarked { get; set; }
}
public class Rhino : IAnimal
{
public string Name { get; set; }
//new Type GetType() { return typeof(Rhino); }
public bool HasHorn { get; set; }
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IAnimal animal1 = new Dog { Name = "Ben", TimesBarked = 30 };
IAnimal animal2 = new Rhino { Name = "James" };
MessageBox.Show($"GetType : {animal1.GetType()}");
PeopleWillTellYouToNotDoThis(animal1);
PeopleWillTellYouToNotDoThis(animal2);
}
private void PeopleWillTellYouToNotDoThis(dynamic inAnimal)
{
MessageBox.Show($"GetType : {inAnimal.GetType()}");
//The following works. But, you should probably really use 'IS' to see if you have a RHINO or not
try { MessageBox.Show($"HasHorn : {inAnimal.HasHorn}"); } catch { };
}
}
}
答案 2 :(得分:1)
全新的C#功能,“模式匹配”开关语句(请查看底部的the Switch Statement docs)可以为您提供帮助。
我一起经历了一个快速接口和几个实现该接口的类:
public interface IAnimal
{
string Speak();
}
public class Cat : IAnimal
{
public string Speak()
{
return "Meow";
}
}
public class Dog : IAnimal
{
public string Speak()
{
return "Woof";
}
}
然后,我创建了IAnimal
的集合,并使用switch
语句找出了什么:
var animals = new List<IAnimal>
{
new Cat(), new Dog(), new Cat()
};
foreach (var animal in animals)
{
switch (animal)
{
case Cat cat:
Debug.WriteLine("This is a cat");
break;
case Dog dog:
Debug.WriteLine("This is a dog");
break;
}
}
输出如下:
这是一只猫
这是一条狗
这是一只猫
我没有显示它,但是cat
和dog
变量是很好的,类型正确的对象引用,可以在范围内使用它们。
但是,正如@BradleyDotNET所提到的,这通常表明设计或实现不正确。