dotnet/runtime

CorrelationManager.LogicalOperationStack.Clone() is shallower than in .NET Framework

Open

#38,176 opened on Jun 19, 2020

View on GitHub
 (10 comments) (0 reactions) (0 assignees)C# (5,445 forks)batch import
area-System.Diagnostics.TraceSourcedocumentationhelp wanted

Repository metrics

Stars
 (17,886 stars)
PR merge metrics
 (Avg merge 12d 11h) (661 merged PRs in 30d)

Description

Description

The Clone method of the Stack returned by CorrelationManager.LogicalOperationStack changed behavior between .NET Framework and .NET Core.

  • In .NET Framework 4.8, Clone returns a new Stack that initially contains the same items as the original, but otherwise works independently. Output from the demo built for net4.8:
    Operations: inner,outer
    Operations: inner,outer
    
  • In .NET Core 2.1, Clone returns a new instance of a class derived from Stack, but if items are later pushed or popped in the original stack, then the clone also updates. Output from the demo built for netcoreapp2.1:
    Operations: inner,outer
    Operations:
    

Source code for the demo:

using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Trace.CorrelationManager.StartLogicalOperation("outer");
            Trace.CorrelationManager.StartLogicalOperation("inner");

            var clone = (Stack)Trace.CorrelationManager.LogicalOperationStack.Clone();
            Console.WriteLine("Operations: {0}", string.Join(",", clone.Cast<object>()));

            Trace.CorrelationManager.StopLogicalOperation();
            Trace.CorrelationManager.StopLogicalOperation();

            Console.WriteLine("Operations: {0}", string.Join(",", clone.Cast<object>()));
        }
    }
}

Configuration

.NET Framework 4.8 vs. .NET Core 2.1. Windows 10 version 2004 x64.

Regression?

A difference from .NET Framework, at least. It is not causing any problem for me, but it is a surprise and does not seem to have been documented elsewhere.

Other information

Workaround: call ToArray instead of Clone. GetEnumerator on the array will yield the inmost logical operation first, just like with Clone. In contrast, new Stack(Trace.CorrelationManager.LogicalOperationStack) would reverse the order.

The Clone implementation came from https://github.com/dotnet/corefx/pull/12527#discussion_r83333871.

Contributor guide