【问题标题】:Anonymously typed List or List of Objects匿名输入的列表或对象列表
【发布时间】:2012-07-25 10:51:47
【问题描述】:

我有以下问题(简化)。

我有一份狗的名单:

public List<Dog> dogs { get; set; }

我目前通过在视图中将其转换为 json 对象来访问此列表:

@(new HtmlString(@Json.Encode(@ViewBag.dogs)))

然后我使用 javascript 遍历这个 json 对象并将其显示在页面上。

我想将汽车添加到此列表中。

但是,由于列表是强类型的 dogs 列表,我的第一个想法是创建列表,因为 dogscars 有一个共同点,它们都是对象。

当我尝试将我的狗列表更改为 objects 列表时,我收到以下错误

Cannot implicitly convert type 'System.Collections.Generic.List<object>' to System.Collections.Generic.List<dog>

我对此进行了研究,发现 this 问题对我没有多大帮助,只是告诉我我无法获得狗和汽车的清单。然而,就我的目的而言,这并不合适。我需要我的列表同时包含狗和汽车,以便我可以在我的应用程序中访问它们。

我预计会被建议的一个解决方案是我有两个单独的列表,并发出两个单独的 ajax 请求。但是,我需要按特定顺序(基于它们的创建时间)混合汽车和狗,这样解决方案并不理想。

简而言之,我想知道实现这一目标的最佳方法是什么。也许我走错了方向,所以如果有意义的话,我不反对做一些完全不同的事情。

一如既往地感谢您的帮助!

编辑:我已经尝试了演员阵容,而且效果很好。但是,我需要访问 dog 的属性(我们称之为“毛皮”),我似乎无法做到这一点(我需要再次施法吗?)

'object' does not contain a definition for 'fur'

【问题讨论】:

  • 在系统中的某个地方,您仍然将dogs 属性定义为List&lt;Dog&gt; 的类型。否则它应该可以工作。
  • @mellamokb 某处?你是说他在哪里宣布狗? ;)
  • @Mansfield 是的,您需要转换回DogCar 才能使用对象的属性。但考虑一下:你怎么知道列表中的任意objectDog 还是Car

标签: c# asp.net-mvc json list object


【解决方案1】:

只有当狗和汽车实现相同的接口或扩展相同的类(例如对象,然后您可以在条件中使用 typeof 对它们执行一些操作)时,您才能创建同时包含狗和汽车的列表。

编辑:

简单示例

using System;
using System.Collections.Generic;

namespace Polymorphism
{
    class Program
    {
        public class Car
        {
            public string Drive()
            {
                return "Wrrrr!";
            }
        }

        public class Dog 
        {
            public string Talk()
            {
                return "Woof";
            }
        }

        static void Main()
        {
            var car = new Car();
            var dog = new Dog();

            List<object> list = new List<object>();
            list.Add(car);
            list.Add(dog);

            foreach (object o in list)
            {
                if (o is Car)
                    Console.WriteLine((o as Car).Drive());
                else
                    Console.WriteLine((o as Dog).Talk());
            }
        }
    }
}

我很抱歉该代码,但我从 Wikipedia 复制并使用 Ideone 进行了编辑

【讨论】:

  • +1 只是要添加一个显示抽象基类和接口的答案:)
  • 听起来 OP 有一个他想要访问的属性“fur”。我想你可以创建一个具有属性“fur”的接口,并且汽车继承它......我见过一辆毛茸茸的汽车,虽然,它的动作叫笨笨……
  • @jsmith:哈哈 :) 在这种情况下,只有狗具有“毛皮”属性。这辆车很无毛。
  • 有时候不爱车的时候可以去wild
【解决方案2】:

我不太清楚汽车从哪里进来,为什么你不能一开始就将你的财产改为List&lt;object&gt;,但你可以这样做:

List<object> objects = foo.Dogs.Cast<object>().ToList();

或者在 C# 4 中,您可以使用泛型协方差并编写:

List<object> objects = foo.Dogs.ToList<object>();

【讨论】:

  • 我只是将属性更改为对象列表。我从链接的问题中推断出的是,我无法将两种不同类型的对象放在同一个列表中。也许我理解错了?
  • @Mansfield:听起来你误会了。 List&lt;object&gt; 当然可以包含对Dog 对象和Car 对象的引用。链接的问题描述了为什么不能将 List&lt;object&gt; 类型的对象转换为 List&lt;string&gt; 或反之亦然。
  • 看起来是这样。我尝试了演员阵容并有所帮助,但现在我遇到了一个新问题(请参阅我对问题的编辑)
  • @Mansfield:嗯,是的 - 如果你知道你有一个object,你就不会知道 Dog 特定的属性,对吗?如果你真的想抛开编译时安全问题,你可以使用List&lt;dynamic&gt;...
  • 动态版+1!谁需要编译时安全!她走到窗外!
【解决方案3】:

在列表中包含不同对象并访问它们共有的属性的最简单方法是在类上使用接口。

例如:

public interface ICoated {
    string Coating { get; set; }
}

public class Dog : ICoated {
    public string Coating {
        get { return Fur; }
        set { Fur = value; }
    }
}

public class Car: ICoated {
    public string Coating {
        get { return PaintJob; }
        set { PaintJob = value; }
    }
}

然后您将使用List&lt;ICoated&gt; 来访问都涂有某种东西的对象。显然,如果你有很多共同的属性,你就会适当地扩展这个模型。

【讨论】:

    【解决方案4】:

    尝试找出两个对象之间的共同点并使用基类或接口。如果你使用了一个接口,你可能会看到它是这样的:

    public interface IAnimal{
       Fur Fur{ get; set; }
       bool CanBark { get; set;}
    }
    
    public class Dog : IAnimal {
       public Fur Fur{ get; set; }
       public bool CanBark { get; set;}
    }
    
    public class Cat: IAnimal {
       public Fur Fur{ get; set; }
       public bool CanBark { get; set;}
    }
    
    public class Fur{
        public string Color {get;set;}
        public int Length {get;set}
    }
    

    等等等等

    那么,您的列表可以是:

    public List<IAnimal> dogs { get; set; }
    public List<IAnimal> cats{ get; set; }
    

    (宠物)深思

    【讨论】:

    • jsmith - 我知道,但添加了我的错误夫人 :-)
    【解决方案5】:

    我可能会创建一个具有共享属性和“类型”属性的接口。

    public enum CrazyObjectType
    {
        Dog,
        Car
    }
    
    public interface ICrazyObject
    {
        DateTime Date { get; }
        CrazyOjbectType MyObjectType { get; }
    }
    
    public class Dog : ICrazyObject
    {
        public Dog()
        {
            MyObjectType = CrazyObjectType.Dog;
        }
    
        public DateTime Date { get; }
        public CrazyObjectType MyObjectType { get; }
    }
    
    public class Car : ICrazyObject
    {
        public Car()
        {
            MyObjectType = CrazyObjectType.Car;
        }
    
        public DateTime Date { get; }
        public CrazyObjectType MyObjectType { get; }
    }
    

    然后,您可以使用 List&lt;ICrazyObject&gt; 代替 List&lt;object&gt;,然后在投射到汽车或狗之前检查其类型..

    foreach (var myObject in myObjects)
    {
        if (myObject.MyObjectType == CrazyObjectType.Car)
        {
            var myCar = (Car)myObject;
            //Do Stuff with myCar here.
        }
    }
    

    这使您可以安全地在转换之前了解您的类型。然后,您在类型汽车中具有与狗不同的任何属性。您可以轻松、安全地访问!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多