C# Cast接口及其实现
我有一个接口,它由更多的类实现,这些类存储了额外的信息。我需要能够转换实现,而无需明确说明这是一个实现C# Cast接口及其实现,c#,C#,我有一个接口,它由更多的类实现,这些类存储了额外的信息。我需要能够转换实现,而无需明确说明这是一个实现 public interface IAnimal { string Name { get; set; } Type GetType(); } public class Dog : IAnimal { public string Name { get; set; } Type GetType() {return typeof(Dog);} public
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
。我可以更改接口及其实现,但不能更改方法
我不知道我将得到哪个对象,所以我必须做一些东西,它可以将任何东西转换为它的原始类型
那你打算怎么处理它呢?因为您不知道类型,所以不知道可以调用什么方法,等等。这就是原始解决方案返回对象的原因
您可以使用dynamic
,但是如果您尝试使用一个不存在的方法,那么它只会抛出。最接近的方法是简单的is
检查(为了简洁起见,C#7模式匹配):
大肥肉免责声明:向下广播是一个巨大的危险信号。当你甚至不知道该期待哪种类型时,向下投射更糟糕。您的设计几乎肯定需要重新考虑
我不知道我将得到哪个对象,所以我必须做一些东西,它可以将任何东西转换为它的原始类型
那你打算怎么处理它呢?因为您不知道类型,所以不知道可以调用什么方法,等等。这就是原始解决方案返回对象的原因
您可以使用dynamic
,但是如果您尝试使用一个不存在的方法,那么它只会抛出。最接近的方法是简单的is
检查(为了简洁起见,C#7模式匹配):
大肥肉免责声明:向下广播是一个巨大的危险信号。当你甚至不知道该期待哪种类型时,向下投射更糟糕。您的设计几乎肯定需要重新思考。不确定您的最终目标是什么。如果你不想使用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 { };
}
}
}
不确定,你的结局是什么。如果你不想使用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 { };
}
}
}
全新的C#功能,一个“模式匹配”开关语句(请看,靠近底部)可以帮助您解决问题
我通过一个快速接口和几个实现它的类:
public interface IAnimal
{
string Speak();
}
public class Cat : IAnimal
{
public string Speak()
{
return "Meow";
}
}
public class Dog : IAnimal
{
public string Speak()
{
return "Woof";
}
}
然后,我创建了一个IAnimal
s的集合,并使用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;
}
}
var动物=新列表
{
新猫(),新狗(),新猫()
};
foreach(动物中的动物变量)
{
开关(动物)
{
案例类别:
Debug.WriteLine(“这是一只猫”);
打破
个案狗只:
这是一只狗;
打破
}
}
此操作的输出如下所示:
这是一只猫
这是一只狗
这是一只猫
我没有显示它,但是cat
和dog
变量是非常好的、类型良好的对象引用,可以在范围内使用它们
但是,正如@BradleyDotNET所提到的,这通常是一个糟糕的设计或实现的标志。全新的C#功能,一个“模式匹配”开关语句(请看,靠近底部)可以帮助您解决问题
我通过一个快速接口和几个实现它的类:
public interface IAnimal
{
string Speak();
}
public class Cat : IAnimal
{
public string Speak()
{
return "Meow";
}
}
public class Dog : IAnimal
{
public string Speak()
{
return "Woof";
}
}
然后,我创建了一个IAnimal
s的集合,并使用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;
}
}
var动物=新列表
{
新猫(),新狗(),新猫()
};
foreach(动物中的动物变量)
{
开关(动物)
{
案例类别:
Debug.WriteLine(“这是一只猫”);
打破
个案狗只:
这是一只狗;
打破
}
}
此操作的输出如下所示:
这是一只猫
这是一只狗
这是一只猫
我没有显示它,但是cat
和dog
变量是非常好的、类型良好的对象引用,可以在范围内使用它们
但是,正如@BradleyDotNET所提到的,这通常是设计或实现糟糕的标志。仅供记录;需要这样做是一个巨大的危险信号。为什么要将GetType()
作为界面的一部分object
已经包含了这一点。如果您必须查询每个对象以试图找出其实际类型,则会破坏接口的用途……这似乎是访问者模式的合适位置,IAnimal
接口具有一个无效接受(IAnimalVisitor Visitor)
方法,当你调用另一个对象时,如果animal
不是Dog
,会发生什么情况。需要知道类型(animal)
的方法?扔?什么也不做?将其转换为Dog
,即使它是,比如说,Cat
,只是为了记录;需要这样做是一个巨大的危险信号。为什么要将GetType()
作为界面的一部分object
已经包含了这一点。如果您必须查询每个对象以试图找出其实际类型,则会破坏接口的用途……这似乎是访问者模式的合适位置,IAnimal
接口具有一个无效接受(IAnimalVisitor Visitor)
方法,当你调用另一个对象时,如果animal
不是Dog
,会发生什么情况。需要知道类型(animal)
的方法?扔?什么也不做?将其转换为Dog
,即使