简体   繁体   中英

Why can't I pass a lambda expression as a parameter in the Immediate Window in Visual Studio 2019?

Note: The question is not "Why can't I use lambda expressions in the Immediate Window?" That is working fine.

When I try to pass a lambda expression as a parameter to a call in the Immediate Window, I get a message back stating "Evaluation of native methods in this context is not supported." Why does this restriction exist and is there a way around it?

For more context, in my main project I have hierarchical data which is occasionally useful to visualize while debugging. To facilitate this, I added a routine that dumps information back to the Immediate Window (via Debug.WriteLine) when invoked, showing the hierarchy (via indentation) along with salient properties of the objects in the hierarchy. Each object has many properties and as I often don't know what I need to see beforehand, I thought it might be neat to add an optional parameter Func< type , Object> to my dump routine so that I could highlight a particular term of each object on a given invocation.

In the example code below, I've simplified the hierarchy to a simple collection, but the idea is the same and it reproduces the error.

At the breakpoint, I can issue the following command in the Immediate Window

collection.DumpData();

and the output is what I would expect

Item info: Id = 1, Property = foo

Item info: Id = 2, Property = heidy

However, if I pass a lambda expression such as

collection.DumpData(o => o.OtherProperty);

I get the following error:

Evaluation of method ReproduceImmediateWindowLimitation.ItemCollection.DumpData(System.Func`2<ReproduceImmediateWindowLimitation.exe.ReproduceImmediateWindowLimitation,Item. object>) calls into native method System.Diagnostics.Debugger.IsLogging(). Evaluation of native methods in this context is not supported.

This error is not specific to Debug.WriteLine. I get the same basic error if I use System.Diagnostics.Trace or if I collect the output lines and write them to a file.

The same problem happens if I assign the lambda expression to a variable beforehand

Func<Item, Object> immediate = o => o.OtherProperty;
collection.DumpData(immediate);

The closest thing I could find to this problem on stackoverflow is this from Marcus where he attributes the problem to EF internals but given my problem I do not believe this is the case.

Obviously I could get around this problem by adding more properties to the output of my dump routine or via reflection, but those options are a lot less flexible.

Example code:

namespace ReproduceImmediateWindowLimitation
{
    class Program
    {
        static void Main(string[] args)
        {
            var collection = new ItemCollection
            {
                new Item { ItemId = 1, Property = "foo", OtherProperty = "bar" },
                new Item { ItemId = 2, Property = "heidy", OtherProperty = "ho" }
            };

            System.Diagnostics.Debugger.Break();

        }
    }

    class ItemCollection : List<Item>
    {
        public void DumpData(Func<Item, Object> highlightTerm = null)
        {
            foreach (var item in this)
            {
                object highlightTermResult = null;
                if (highlightTerm != null)
                {
                    var temp = highlightTerm(item);
                    if (temp == null)
                    {
                        highlightTermResult = "n/a";
                    }
                    else
                    {
                        highlightTermResult = String.Format(">> highlighted term {0} <<", temp);
                    }
                }

                System.Diagnostics.Debug.WriteLine(
                    "Item info: Id = {0}, Property = {1} {2}",
                    item.ItemId,
                    item.Property,
                    highlightTermResult ?? "");
            }
        }
    }

    class Item
    {
        public int ItemId { get; set; }
        public string Property { get; set; }
        public string OtherProperty { get; set; }
    }
}

Update:

To address Seabizkit's point, the use of a collection here is just for example purposes. I can further simplify the code and still reproduce the problem.

item.DumpData();

yields

Item info: Id = 1, Property = foo

as expected, but

item.DumpData(o => o.OtherProperty);

yields

ReproduceImmediateWindowLimitation.Item.DumpData(System.Func`2<ReproduceImmediateWindowLimitation.exe.ReproduceImmediateWindowLimitation,Item. object>) calls into native method System.Diagnostics.Debugger.IsLogging(). Evaluation of native methods in this context is not supported.

namespace ReproduceImmediateWindowLimitation
{
    class Program
    {
        static void Main(string[] args)
        {
            var item = new Item { ItemId = 1, Property = "foo", OtherProperty = "bar" };

            System.Diagnostics.Debugger.Break();

        }
    }

    class Item
    {
        public int ItemId { get; set; }
        public string Property { get; set; }
        public string OtherProperty { get; set; }

        public void DumpData(Func<Item, Object> highlightTerm = null)
        {
            object highlightTermResult = null;
            if (highlightTerm != null)
            {
                var temp = highlightTerm(this);
                if (temp == null)
                {
                    highlightTermResult = "n/a";
                }
                else
                {
                    highlightTermResult = String.Format(">> highlighted term {0} <<", temp);
                }
            }

            System.Diagnostics.Debug.WriteLine(
                "Item info: Id = {0}, Property = {1} {2}",
                this.ItemId,
                this.Property,
                highlightTermResult ?? "");
        }
    }
}

Update 2: As mentioned in the comment to StriplingWarrior, I tried enabling native code debugging in the project. Also just for grins I tried marking the DumpData method as unsafe (with the /unsafe compiler option). Neither changed the behavior.

this is not an answer just stating that not all code is available to reproduce...

this does not throw and results in

Item info: Id = 1, Property = foo >> highlighted term bar <<

in the console.

var item = new Item { ItemId = 1, Property = "foo", OtherProperty = "bar" };

try
{
    item.DumpData(o => o.OtherProperty);
}
catch (Exception ex)
{
    throw;
}


System.Diagnostics.Debugger.Break();

class Item
{
    public int ItemId { get; set; }
    public string Property { get; set; }
    public string OtherProperty { get; set; }

    public void DumpData(Func<Item, Object> highlightTerm = null)
    {
        object highlightTermResult = null;
        if (highlightTerm != null)
        {
            var temp = highlightTerm(this);
            if (temp == null)
            {
                highlightTermResult = "n/a";
            }
            else
            {
                highlightTermResult = String.Format(">> highlighted term {0} <<", temp);
            }
        }
    
        Console.WriteLine("Item info: Id = {0}, Property = {1} {2}",
            this.ItemId,
            this.Property,
            highlightTermResult ?? "");

        System.Diagnostics.Debug.WriteLine(
            "Item info: Id = {0}, Property = {1} {2}",
            this.ItemId,
            this.Property,
            highlightTermResult ?? "");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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