【问题标题】:Why does this method keep returning dynamic despite the return type in the signature?为什么尽管签名中有返回类型,但此方法仍保持动态返回?
【发布时间】:2014-10-24 13:01:00
【问题描述】:

所以激活器返回的类型(此处未显示)只是我创建的 POCO。没有什么特别的。但是尽管如此,GetWrapperGetWrapper<T> 的返回类型是返回的对象的类型是动态的,因此智能感知没有看到正在返回的实际类的任何属性。有什么想法吗?

更新: 对不起,乔恩:

public static T GetWrapper<T>(object type, dynamic obj)
   where T : class, IRedditObject
{
    return GetWrapper(type, obj) as T;
}

public static object GetWrapper(object type, dynamic obj)
{
    return Activator.CreateInstance(Types[type.ToString()], obj);
}

public class LinkWrapper : IRedditObject
{
    private readonly dynamic _link;

    public string Kind { get { return "t3"; } }
    public dynamic Data { get { return _link.data; } }

    public LinkWrapper(dynamic link)
    {
        _link = link;
    }

    public string Domain { get { return Data.domain; } }
}

[TestMethod]
public void Test()
{
    var proxy = new SubredditProxy();
    var dotnet = proxy.GetSubredditAsync("dotnet").Result;

    var child1 = dotnet.data.children[0];

    // this is being returned as dynamic
    var obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>(child1.kind, child1);


    Assert.IsNotNull(obj);
}

【问题讨论】:

  • 请将您的代码放在问题中的text中。很难按原样阅读。 (演示问题的简短但完整程序也不会受到伤害。我们不知道child1.kindchild1的类型。)
  • 还有child1child1.kind的类型?
  • 这些都是动态的。我正在从 reddit 中提取一个 json 结果并将其反序列化为动态的,然后尝试将它们包装在另一个对象中。在这个阶段几乎就是这样。唯一缺少的部分是 JsonConvert.DeserializeObject&lt;dynamic&gt;(httpResultText);,它是 GetSubredditAsync 的结果
  • 我更新了帖子以显示包装器
  • 对——那就是问题所在。看我的回答:)

标签: c# .net dynamic


【解决方案1】:

我强烈怀疑child1child1.kind 属于dynamic 类型,这意味着该表达式被视为动态绑定表达式,尽管其他情况。

这是一个简短但完整的例子来说明我的意思:

using System;

class Test
{
    public static T Foo<T>(object x)
    {
       return default(T);
    }

    public static void Main(string[] args)
    {
        object a = new object();
        dynamic b = a;

        var c = Foo<string>(a);
        var d = Foo<string>(b);

        Console.WriteLine(c.SomeRandomMember); // Invalid
        Console.WriteLine(d.SomeRandomMember); // Valid
    }
}

无效语句是无效的,因为c 的类型是string - 但后面的语句没问题,因为d 的类型是dynamic

即使它在执行时可以绑定到只有一种可能的方法 - 即使该绑定将始终有效 - 基本规则是几乎任何涉及dynamic 值的表达式被认为是dynamic 类型。 (有一些例外,例如asnew。)

要使您的返回值非动态,只需将您的值转换为object

var obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>
     ((object) child1.kind, (object) child1);

这将是一个静态绑定的调用。或者您可以将其保留为动态绑定调用,并使用从 dynamic 类型的表达式到其他类型的隐式转换:

LinkWrapper obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>(child1.kind, child1);

【讨论】:

  • 有趣。好的,所以我还注意到,如果我放弃var,那么演员阵容就会正确地举行
  • @Sinaesthetic:是的——请看我回答的结尾。您基本上是在此时动态地进行调用,然后要求编译器在最后将dynamic 转换为正确的类型。我更喜欢“调用前转换”方法,以便尽可能多地静态绑定代码,但这是个人喜好。
  • ^^ 你在我发布的时候更新了你的帖子,哈哈。好的。太好了,谢谢!
【解决方案2】:

我同意当前的答案 (https://stackoverflow.com/a/25586620/1942762),但这里是 C# 编程指南 (Overload resolution with arguments of type dynamic) 中的解释:

如果方法调用中的一个或多个参数具有动态类型,或者如果方法调用的接收者是动态类型,则重载解决发生在运行时而不是编译时。

您的参数可能是动态类型的,因此您的 IDE 也会将 obj 视为动态参数

【讨论】:

    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多