【问题标题】:Cannot implicitly convert anonymous type #1[] to anonymous type #2[]无法将匿名类型 #1[] 隐式转换为匿名类型 #2[]
【发布时间】:2013-10-07 12:02:21
【问题描述】:

我有以下场景:

public JsonResult ChangeFilterList(int option)
{
    var data = new[] { new { Text = "Unknown option", Value = -1 } };
    switch (option)
    {
        case 2: data = _departmentnameRepository.All.Select(x => new { Text = x.DeptName, Value = x.Id }).ToArray();
            break;
        case 3: data = Session["projectid"] == null
                ? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
                : _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray();
            break;
        default: data = _userRepository.All.Select(x => new { Text = x.DisplayName, Value = x.UserID }).ToArray();
            break;
    }            

    return Json(data, JsonRequestBehavior.AllowGet);
}

case2default 看起来不错,但抱怨案例 3(有条件)说:Cannot implicitly convert type 'AnonymousType#1[]' to 'AnonymousType#2[]'?: 不应该能够决定类型,因为我已经提供了匿名的蓝图为 var data = new[] { new { Text = "Unknown option", Value = -1 } };

解决方案:

@Darin Dimitrov 的回答很好,但我想对匿名类型进行一些测试(简单的情况总是需要它)。 正如@Douglas 怀疑的那样:我的assetSequenceRepository 提供id 作为long 和匿名Value 支持int 而不是long。由于 C# 编译器不会将 long 隐式转换为 int,因此我得到了错误。编译sn-p是:

public JsonResult ChangeFilterList(int option = 3)
        {
            var data = new[] { new { Text = "Unknown option", Value = long.MaxValue } };
            switch (option)
            {
                case 2: data = _departmentnameRepository.All.Select(x => new { Text = x.DeptName, Value = (long)x.Id }).ToArray();
                    break;
                case 3: data = Session["projectid"] == null
                        ? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
                        : _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray();
                    break;
                default: data = _userRepository.All.Select(x => new { Text = x.DisplayName, Value = (long)x.UserID }).ToArray();
                    break;
            }            

            return Json(data, JsonRequestBehavior.AllowGet);
        }

【问题讨论】:

  • 一个简单的解决方法是将您的?: 语句替换为if…else 块。
  • 我试过了,效果一样,不知道怎么回事。
  • if…else 会收到什么错误消息?您是否在if 分配、else 分配或两者中都遇到错误?
  • @BishnuRawal 请注意,将数据初始化为 new[] { new { Text = "Unknown option", Value = -1 } } 是不必要的,因为它将在 switch 块中被丢弃。
  • @Douglas:ifelse 两次出现相同错误。

标签: c# linq entity-framework asp.net-mvc-4 anonymous-types


【解决方案1】:

您在这里对编译器进行了真正的测试。只需编写一个视图模型来结束它的痛苦并使事情更加明确:

public class MyViewModel
{
    public int Value { get; set; }
    public string Text { get; set; }
}

然后将您的 LINQ 查询投影到此视图模型,以避免使用条件运算符和匿名类型可能产生的任何歧义:

public ActionResult ChangeFilterList(int option)
{
    var data = new[] 
    { 
        new MyViewModel { Text = "Unknown option", Value = -1 } 
    };

    switch (option)
    {
        case 2: data = _departmentnameRepository
            .All
            .Select(x => new MyViewModel { Text = x.DeptName, Value = x.Id })
            .ToArray();
            break;
        case 3: data = Session["projectid"] == null
                ? _assetSequenceRepository
                    .All
                    .Select(x => new MyViewModel { Text = x.AssetShotName, Value = x.Id })
                    .ToArray()
                : _assetSequenceRepository
                    .FindBy(p => p.ProjectId == (int)Session["projectid"])
                    .Select(x => new MyViewModel { Text = x.AssetShotName, Value = x.Id })
                    .ToArray();
            break;
        default: data = _userRepository
            .All
            .Select(x => new MyViewModel { Text = x.DisplayName, Value = x.UserID })
            .ToArray();
            break;
    }            

    return Json(data, JsonRequestBehavior.AllowGet);
}

【讨论】:

  • 谢谢达林,这是唯一的解决方法。我想到了,但考虑到琐碎的案例,我最终匿名了。
【解决方案2】:

我的猜测是您的 FindBy 方法返回的对象的属性类型与您期望的类型不同(例如,int? 而不是 int)。尝试指定类型转换以确保您的匿名类型具有正确的定义:

case 3: data = Session["projectid"] == null
             ? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
             : _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = (string)x.AssetShotName, Value = (int)x.Id }).ToArray();
        break;

关键变化是:

new { Text = (string)x.AssetShotName, Value = (int)x.Id })
                  ↖    explicit type casts    ↗

【讨论】:

  • 你是对的,assetSequenceRepository返回id只要,这样的新手错误,现在编译完美。谢谢,我接受你的回答。
【解决方案3】:

下面的测试代码编译就好了:

public void Test(int option, string parameter)
{
    var data = new[] { new { Text = "Unknown option", Value = -1 } };

    switch(option)
    {
        case 2:
            data = Enumerable.Range(1, 4)
                             .Select(x => new { Text = x.ToString(), Value = x })
                             .ToArray();
            break;
        case 3:
            data = (new Random()).Next(2) % 2 == 1
                ? Enumerable.Range(1, 6)
                            .Select(x => new { Text = x.ToString(), Value = x })
                            .ToArray()
                : Enumerable.Range(1, 2)
                            .Select(x => new { Text = x.ToString(), Value = x })
                            .ToArray();
            break;
        default:
            data = Enumerable.Range(1, 3)
                             .Select(x => new { Text = x.ToString(), Value = x })
                             .ToArray();
            break;
    }
}

我只是将您的存储库调用更改为 Enumerable.Range()Select lambda 以获得正确的 string/int 属性值。

我猜,您所展示的并不完全是您尝试编译的代码。在您的真实代码中,您有一个名称不匹配的属性(例如不正确的大小写)或不正确的类型。

您可以通过将鼠标指针悬停在ToArray() 呼叫上来尝试找出答案。工具提示上会印有a is new { string Text, int Value }

【讨论】:

  • Marin,我敢肯定,在每种情况下,我的开发代码都与提供的 { Text = "Unknown option", Value = -1 } 相同。
猜你喜欢
  • 2016-01-11
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
相关资源
最近更新 更多