Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 代码理解问题_C# - Fatal编程技术网

C# 代码理解问题

C# 代码理解问题,c#,C#,今天早上我在读一段源代码时,遇到了一个我不理解的C代码示例: public bool Dequeue(out T value) { Node head; Node tail; Node next; while (true) { // read head head = this.head; tail = this.tail; next = head.Next; // Are

今天早上我在读一段源代码时,遇到了一个我不理解的C代码示例:

public bool Dequeue(out T value)
{
    Node head;
    Node tail;
    Node next;

    while (true)
    {
        // read head
        head = this.head;
        tail = this.tail;
        next = head.Next;

        // Are head, tail, and next consistent?
        if (Object.ReferenceEquals(this.head, head))
        {
           // Source code continues here...
        }
        // And here...
    }
}
我遇到了一个问题,它包含
Object.ReferenceEquals()


如果我理解得很好,源代码作者想比较
this.head
head
,但在上面几行中,他只写了
head=this.head

这句话主要来自
C++
的背景,对我来说毫无意义。此外,在某些情况下,
Object.ReferenceEquals()
行似乎抛出了一个
System.NullReferenceException
,所以它肯定会做些什么,我就是不知道是什么

你能帮我理解这条线的作用和可能的原因吗

如果需要,这里是
节点
类定义(我猜它是一个“模板”类,不确定C#的措辞):

多谢各位

编辑:该方法的其余部分,供询问者使用
public void排队(T值)
{
//从空闲列表中分配一个新节点
节点值节点=新节点(值);
while(true)
{
Node tail=this.tail;
Node next=tail.next;
//尾巴和下一个一致吗
if(Object.ReferenceEquals(tail,this.tail))
{
//尾部是否指向最后一个节点?
if(Object.ReferenceEquals(next,null))
{
如果(Object.ReferenceEquals(
联锁比较交换(参考tail.Next,valueNode,Next),
下一个
)
)
{
联锁。比较交换(参考this.tail、valueNode、tail);
打破
}
}
else//tail未指向最后一个节点
{
//尝试将尾部摆动到下一个节点
联锁。比较交换(参考this.tail,next,tail);
}
}
}
}

如果
this.head
this.tail
是公共的,则可以在循环运行时更改它们
Object.ReferenceEquals
检查它们是否与方法执行时相同

如果没有整个课堂/上下文,很难给出更完整的答案

他刚刚写了这个

这是一项作业,与比较它们无关。注意,这是关于一个字段
head
和一个本地变量
this.head

if(Object.ReferenceEquals(this.head,head))


在这里,作者希望比较
this.head
head
,同时确保相等是基于它们的引用(地址),而不是基于
=
Equals()的任何(可能)重载


我假设本地var
head
在循环中被更改,这使得它成为一个有争议的命名

ReferenceEquals是一个函数,用于确保一个对象的两个实例是完全相同的对象,而不仅仅是两个具有相同值的对象。文档可在此处找到()。至于该语句的目标,如果这段代码是在多线程上下文中执行的,那么他可能会试图确保没有人弄乱了head(非常危险),或者担心有人传入了值类型(危险,但更好的检查方法)


编辑:随着进一步的代码发布,它看起来像是第一件事。他使用ReferenceEquals试图在有多个线程的情况下捕捉竞争条件(如果不是多线程的,他就不会使用InterlocatedExchange)。代码似乎基本上是在尝试执行一个操作,如果有人在中途对其进行了更改,只需再次尝试(while(true))。使用关键部分或信号量来确保没有人修改您的值可能更为优雅,而不是简单地希望您可以检查它们是否修改了。原因是,在IF之后,但在InterlocatedExchange之前,可能会有人修改您的值,这会引入错误

看起来像一个链表。出列看起来像一个递归函数。 所以,要么“下一步”对节点的“头部”部分执行操作,要么它并行运行,在继续之前,他试图检查内容是否仍在原来的位置。最后一部分做得不正确,因为在进入关键部分时应该使用信号量,否则您将遇到竞争条件,它迟早会失败

该方法用于执行线程安全比较和替换-这意味着该方法应该能够处理队列被外部线程修改的情况。
if
语句试图处理列表被其他线程修改的情况

在哪个类中是
Dequeue
方法所在的对象。ReferenceEquals()
永远不会抛出
NullReferenceException
是否确定异常发生在该位置?是否可以发布该方法的其余部分?这可能会把事情弄清楚。另外,你知道这段代码工作正常吗?@Ophir Yoktan:Done。至少9个月以来,该代码似乎运行良好。然而,从一段时间以来,前面提到的行抛出了一个
NullReferenceException
(我猜是网络问题,我们经常遇到一些问题)@jdehaan:是的。除非堆栈跟踪不可靠?(可能是,我不知道)我认为这句话的主旨是,如果你把一个赋值给另一个,一个ReferenceEquals调用来检查它们是否等同于检查编译器,或者一个穷人的线程安全工具。我认为他遗漏的一点是,这是C#中的一个引用赋值。给C++程序员<代码>节点头;<鳕鱼
private class Node
{
    public T Value;
    public Node Next;

    public Node(T value)
    {
        this.Value = value;
    }
}
    public void Enqueue(T value)
    {
        // Allocate a new node from the free list
        Node valueNode = new Node(value);

        while (true)
        {
            Node tail = this.tail;
            Node next = tail.Next;

            // are tail and next consistent
            if (Object.ReferenceEquals(tail, this.tail))
            {
                // was tail pointing to the last node?
                if (Object.ReferenceEquals(next, null))
                {
                    if (Object.ReferenceEquals(
                            Interlocked.CompareExchange(ref tail.Next, valueNode, next),
                            next
                            )
                        )
                    {
                        Interlocked.CompareExchange(ref this.tail, valueNode, tail);
                        break;
                    }
                }
                else // tail was not pointing to last node
                {
                    // try to swing Tail to the next node
                    Interlocked.CompareExchange<Node>(ref this.tail, next, tail);
                }
            }
        }
    }