匿名类型和动态列表......困惑

发布于 2024-10-15 15:59:13 字数 1019 浏览 1 评论 0原文

我发现 .NET 内部的某些东西的工作方式与我的预期略有不同。我粘贴的代码没有意义,但它是我拥有的更复杂函数的压缩版本。我本质上是获取匿名类型信息作为参数(尚未创建匿名类型的实例),并且我需要创建该类型的列表,填充它,然后返回该列表。现在,我找到了解决方案,但我想知道为什么方法 B 有效但方法 A 无效。

方法 A:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

方法 B:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    System.Collections.IList list;

    list = (System.Collections.IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

再说一次,我不是在寻找解决方案,只是好奇为什么方法 B 有效但方法 A 无效。

谢谢!

I found something inside .NET that works a bit differently that I would have expected. The code I am pasting won't make sense, but it is a condensed version of a much more complicated function I have. I'm essentially getting the anonymous type information as a parameter (no instance created yet of the anonymous type) and I need to create a list of that type, populate it, and then return the list. Now, I found a solution, but I wanted to know why Method B works but not Method A.

Method A:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

Method B:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    System.Collections.IList list;

    list = (System.Collections.IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

Again, I'm not looking for a solution, just curious why Method B works but not Method A.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

叫嚣ゝ 2024-10-22 15:59:14

因为在方法 B 中,您使用的是显式的 IList.Add(object) ,它接受一个对象并尝试将其转换为匿名类型。在方法 A 中,您有一个 List 并且您正在使用通用 Add 方法并尝试添加一个对象,但您收到 RuntimeBinderException 因为它期望正确铸造的类型。如果您没有使用dynamic,您会看到编译器错误。要使用显式 IList.Add,请将方法 A 更改为

((IList)list).Add(
    Activator.CreateInstance(newItem.GetType(), 
        new object[] { Guid.NewGuid(), "Test 2" }));

Because in your method B, you are using the explicit IList.Add(object) which takes an object and tries to cast it to your anonymous type. In method A you have a List<anonymous type> and you're using the generic Add method and trying to Add an object, but you get the RuntimeBinderException because it is expecting the correctly casted type. If you weren't using a dynamic you'd see the compiler error. To use the explicit IList.Add, change your method A with

((IList)list).Add(
    Activator.CreateInstance(newItem.GetType(), 
        new object[] { Guid.NewGuid(), "Test 2" }));
笑脸一如从前 2024-10-22 15:59:14

要使方法 A 起作用,您所需要做的就是动态转换您要添加的激活器结果。很多人没有意识到,C# 动态调用实际上默认使用静态类型来确定方法签名。因此,通过将参数转换为动态,您可以告诉它使用运行时类型。

   static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add((dynamic)Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));

}

All you need to do to make Method A work, is dynamic cast the Activator result that you are adding. Many people don't realize that C# dynamic invocation actually uses static types by default to determine the method signature. So by casting the argument to dynamic as well you are telling it to use the runtime type.

   static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add((dynamic)Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文