创建分层匿名类型

时间:2010-07-30 06:43:37

标签: c# anonymous-types

有没有办法创建引用自身实例的匿名类型?

var root = new { Name = "Root", Parent = ??? };
var child = new { Name = "Child", Parent = root };
var childOfChild = new { Name = "Grand child", Parent = child };

例如,我们可以自己引用委托:

Action run = null;
run = () => run();

另一个例子,我们可以创建匿名类型的通用堆栈:

static Stack<T> CreateStack<T>(params T[] values)
{
    var stack = new Stack<T>();

    foreach (var value in values)
        stack.Add(value);

    return stack;
}

您能想到从自己引用匿名类型的任何方法吗?

2 个答案:

答案 0 :(得分:9)

C#中的匿名类型是 immutable 。因此,所有字段值必须在创建对象之前出现,并且永远不会更改。因此,在C#中直接循环引用匿名类型是不可能的。

VB中的匿名类型是可变的;你可能想办法在VB中做到这一点。

可能有一种方法可以使匿名类型间接引用本身,例如,包含一个委托,该委托在被调用时返回匿名类型的实例。我没有看到任何方法轻易做到这一点,但我也没有看到证明这样做是不可能的。仔细考虑一下,看看你想出了什么!

我认为这个问题仅用于娱乐目的。如果你想制作一个循环引用的对象,请做一个名义上的类型。

答案 1 :(得分:1)

似乎...... C#编译器将拒绝递归地推断类型。以此示例代码为例:

(来自@Eric:正确;类型推理引擎要求在推断出lambda的“输出”类型之前知道lambda的所有“输入”类型)

public void Run()
{
  var k = Generator((str, parent) => new {
    Name = str,
    Parent = parent
  });
}

public Func<string, T, T> Generator<T>(Func<string, T, T> generator)
{
  return (str, obj) => generator(str, obj);
}

此代码段无法编译,错误导致编译器无法推断<T>Generator<T>一起使用...因此我认为这是不可能的。