Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Cast接口及其实现_C# - Fatal编程技术网

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
,即使