简体   繁体   English

这个C#结构有什么问题?

[英]What's wrong with this C# struct?

Note: My question has several parts to it. 注意:我的问题有几个部分。 I'd appreciate it if you would please answer each of the questions, instead of simply telling me what to do to get this to compile. 如果您愿意回答每个问题,我会很感激,而不是简单地告诉我该怎么做才能编译。 :) :)

I'm not by any means good with C#. 我对C#没有任何好处。 In fact, the reason why I don't know much about it is my class is focused on making efficient Algorithms and not really on teaching us .NET. 事实上,我不太了解它的原因是我的课程专注于制作有效的算法而不是真正教我们.NET。 Nevertheless all of our programs must be written in .NET and it hasn't been a problem until just now. 尽管如此,我们所有的程序都必须用.NET编写,直到现在才出现问题。 I have the following code, but it won't compile and I don't really understand why. 我有以下代码,但它不会编译,我不明白为什么。 I have a gut feeling that this should be rewritten altogether, but before I do that, I want to know WHY this isn't allowed. 我有一种直觉,认为这应该完全改写,但在我这样做之前,我想知道为什么不允许这样做。

The point of the struct is to create a linked list like structure so I can add another node to the end of the "list" and then traverse and recall the nodes in reverse order 结构的要点是创建一个类似结构的链表,这样我就可以在“列表”的末尾添加另一个节点,然后以相反的顺序遍历和调用节点

private struct BackPointer
{
    public BackPointer previous;
    public string a;
    public string b;
    public BackPointer(BackPointer p, string aa, string bb)
    {
        previous = p;
        a = aa;
        b = bb;
    }
}

then later in my code I have something to the effect of 然后在我的代码中我有一些效果

BackPointer pointer = new BackPointer();
pointer = new BackPointer(pointer, somestring_a, somestring_b);

The compile error I'm getting is Struct member 'MyClass.BackPointer.previous' of type 'MyClass.BackPointer' causes a cycle in the struct layout 我得到的编译错误是Struct member 'MyClass.BackPointer.previous' of type 'MyClass.BackPointer' causes a cycle in the struct layout

This seems to be an obvious error. 这似乎是一个明显的错误。 It doesn't like the fact that I am passing in the struct in the constructor of the same struct. 它不喜欢我在同一结构的构造函数中传递结构的事实。 But why is that not allowed? 为什么不允许这样做? I would imagine this code would just create a new node in the list and return this node with a pointer back to the previous node, but apparently that's not what would happen. 我想这个代码只会在列表中创建一个新节点并返回该节点,并返回前一个节点,但显然不会发生这种情况。 So what would actually happen then? 那么实际会发生什么呢? Lastly what is the recommended way to resolve this? 最后解决这个问题的推荐方法是什么? I was thinking to just tell it to be unmanaged just handle my pointers manually, but I only really know how to do that in C++. 我想只是告诉它不受管理只是手动处理我的指针,但我真的只知道如何在C ++中做到这一点。 I don't really know what could go wrong in C# 我真的不知道C#会出现什么问题

That's not a pointer; 那不是指针; it's an actual embedded struct value. 它是一个实际的嵌入式struct值。
The whole point of struct s is that they're (almost) never pointers. struct的全部意义在于它们(几乎)从不指针。

You should use a class instead. 你应该使用一个class

But why is that not allowed? 但为什么不允许这样做?

It's a struct - a value type. 它是一个结构 - 一种价值类型。 That means wherever you've got a variable of that type, that variable contains all the fields within the struct, directly inline. 这意味着无论您拥有该类型的变量,该变量都包含结构中的所有字段,直接内联。 If something contains itself (or creates a more complicated cycle) then you clearly can't allocate enough space for it - because it's got to have enough space for all its fields and another copy of itself . 如果某些东西包含自身(或创建一个更复杂的循环),那么你显然无法为它分配足够的空间 - 因为它必须有足够的空间用于其所有字段和另一个自身的副本

Lastly what is the recommended way to resolve this? 最后解决这个问题的推荐方法是什么?

Write a class instead of a struct. 编写一个类而不是结构。 Then the value of the variable will be a reference to an instance, not the data itself. 然后变量的值将是对实例的引用 ,而不是数据本身。 That's how you get something close to "a pointer" in C#. 这就是你如何在C#中获得接近 “指针”的东西。 (Pointers and references are different, mind you.) (请注意,指针和参考文献不同。)

I suggest you read my article on value types and reference types for more information - this is an absolutely critical topic to understand in C#. 我建议你阅读我关于值类型和引用类型的文章以获取更多信息 - 这是在C#中理解的一个绝对重要的主题。

Backpointer HAS to exist before creating a Backpointer, because you can't have a Backpointer without another Backpointer (which would then need another Backpointer and on and on). 在创建Backpointer之前,Backpointer已经存在,因为没有其他Backpointer(然后需要另一个Backpointer,然后打开),你就不能拥有Backpointer。 You simply can't create a Backpointer based on the way you've created it, because, as a struct, Backpointer can never be null. 您根本无法根据创建它的方式创建Backpointer,因为作为结构,Backpointer永远不能为null。

In other words, it's impossible to create a Backpointer with this code. 换句话说,使用此代码创建Backpointer是不可能的。 The compiler knows that, and so it forces you to make something that would work logically. 编译器知道这一点,因此它迫使你做出一些逻辑上有效的东西。

Structs are stored by value. 结构按值存储。 In this case, your struct stores within itself another instance of the same struct. 在这种情况下,您的struct在其自身内存储同一结构的另一个实例。 That struct stores within itself another struct and so on. 该结构本身存储另一个结构,依此类推。 Therefore this is impossible. 因此这是不可能的。 It is like saying that every person in the world must have 1 child. 这就像说世界上每个人都必须有一个孩子。 There is no way this is possible. 这是不可能的。

What you need to use is a class. 你需要使用的是一堂课。 Classes store by reference, which means that it does not store the class within itself, it only stores a reference to that class. 类通过引用存储,这意味着它不会将类存储在其自身中,它只存储对该类的引用。

A CLR struct is by definition a value type . 根据定义,CLR struct值类型 What this means in your context is that the compiler needs to know the exact layout of the type. 这在您的上下文中意味着编译器需要知道该类型的确切布局。 However, it cannot know how to layout a type which contains an instance of itself - does that sound reasonable? 但是,它无法知道如何布局包含自身实例的类型 - 这听起来合理吗? Change the struct to class (which makes your BackPointer to a reference type ) and you'll see it's gonna work out of the box. 将结构更改为类(这使得BackPointer成为引用类型 ),您将看到它将开箱即用。 The reason is that an instance of any reference type has always has the same layout - it is basically just a "pointer" to some location of the managed heap. 原因是任何引用类型的实例总是具有相同的布局 - 它基本上只是托管堆的某个位置的“指针”。 I strongly recommend to read on a bit about the basics of C# or CLI type system. 我强烈建议您先阅读一下C#或CLI类型系统的基础知识。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM