【问题标题】:Convert an Object to a user defined type class object without Reflection in C#在 C# 中将对象转换为不带反射的用户定义类型类对象
【发布时间】:2020-11-23 05:24:19
【问题描述】:

我有以下代码,我在数组中添加一些类对象。

  Object[] ArrayOfObjects = new Object[] {typeof(Person), typeof(Company)};

现在,如果我想遍历我的类项目,如何将每个项目转换回其原始类型(例如 Person 和 Company)?使用反射也许可以做到这一点,但我想知道 C# 是否有一些内置功能来实现这一点。

  foreach (var item in ArrayOfObjects)
  {
     // TODO Convert item back to Original Type (Person or Company)
     // I am doing something like this but not working
     var person  =  Convert.ChangeType(item, typeof(Person));

     //I can not do this too as hardcoding the type inside the loop makes no sense
     var person = item as Person; //I need to convert item as Person or Company so that i can automate the tasks here.
  }

非常感谢。

【问题讨论】:

  • 您不必将它转换回它的类型 - 它已经那种类型。对象的运行时类型(例如Person)和变量的类型(例如System.Object)不是一回事。
  • 请告诉我们你想做什么 - 因为这个问题感觉就像minimal reproducible example。换句话说 - 向我们展示一些示例 TODO 代码,展示您计划如何使用PersonCompany
  • 怀疑你想要的是var person = item as Person; 然后检查它是否是null。或者foreach (var item in ArrayOfObjects.OfType<Person>()).
  • 我的意思是如果是一个人你不需要ChangeType给一个人。它已经是一个(即,如果您调用item.GetType(),它将返回Person)。所以如果item 是一个人,那么var person = item as Person; 就可以正常工作。
  • 但是您的示例 new Object[] {typeof(Person), typeof(Company)}; 正在做其他事情。这是一个 Type 对象数组,而不是每种类型的实例。

标签: c# arrays .net reflection


【解决方案1】:

对您的用例做一些假设,您可能会受益于使用接口来完全消除转换对象的需要

假设您需要执行属于 Company 和 Person 的共享方法 Foo

public interface ObjectWithFoo{
     void Foo();
}
public class Person : ObjectWithFoo{
    ...
}
public class Company: ObjectWithFoo{
    ...
}

然后在您的主代码中创建一个 ObjectWithFoo 列表

ObjectWithFoo[] myArray = new ObjectWithFoo[]{new Person(), new Company()}

然后在你的循环中

foreach(var objectWithFoo in myArray)
    objectWithFoo.Foo();

这样你根本不需要投射,你可以使用所有的接口。额外的好处是,您的数组对您自己和他人的用途变得更加清晰 - 它仅用于属于您的接口的方法/属性。如果您使用对象数组,人们可以轻松添加不受支持的类型或开始在其他地方使用列表,从而使您的代码有点混乱。

【讨论】:

  • 我建议将I 设为接口名称的第一个字母。
【解决方案2】:
using System;

namespace PatternMatching
{
    class Person
    {
        public void PersonMethod() => throw new Exception();
    }

    class Company
    {
        public void CompanyMethod() => throw new Exception();
    }

    class Program
    {
        static void Main(string[] args)
        {
            Object[] ArrayOfObjects = { new Person(), new Company() };

            foreach (var item in ArrayOfObjects)
            {
                if (item is Person person)
                {
                    person.PersonMethod();
                }

                if (item is Company company)
                {
                    company.CompanyMethod();
                }
            }
        }
    }
}

使用模式匹配 (C# 8.0+) https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/may/csharp-8-0-pattern-matching-in-csharp-8-0 你甚至可以使用 switch 模式。

【讨论】:

  • 假设我有 50 个对象,这是我要添加 50 个 if 语句吗?
  • 如果你有 50 个对象,你想这样处理意味着你的设计很糟糕,需要重构(现在 50% 是在开玩笑)。正如我所说,您可以使用 switch 语句,但现在有一些限制。
  • 一个循环中有 50 个对象的设计怎么会很糟糕?
  • 我以为你的意思是 50 种不同的班级类型。我认为,使用 Object[] 来操作它们并不是一个好主意。但是,如果您的意思是只遍历 3-5 类类型的约 50 个对象 - 这当然是解决方案,但您必须避免它。
猜你喜欢
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多