简体   繁体   中英

Why can't I assign a value to a decimal with a ternary operator?

I have a list of objects (using anonymous types) containing a decimal and an integer ID, and I'm building a function to take the sum of the decimals contained within all unique objects in the list.

This is the line of code I wrote:

var result = (objectList.Any()) ? objectList.Distinct().Sum(x => x.DecimalValue) : 0;

However, it always returns a decimal with the value 0 , even though it should be returning the sum - objectList contains five identical objects in my example, so it should return the DecimalValue.

If I replace it with these two lines of code, however, it returns the DecimalValue:

decimal result = 0;
if (objectList.Any()) result = objectList.Distinct().Sum(x => x.DecimalValue);

Why does the second set of lines work, but the first line returns the wrong value? objectList.Any() is true, so it shouldn't be using the false assignment.

Update: I generated the list of anonymous types using this line of code:

var objectList = _ms.Read(cmd, x => new { DecimalValue = x.Field<decimal>("SomeColumnName"), Id = x.Field<int>("SomeColumnId") }).ToList();

_ms is a DAO for MS SQL, and it's running the lambda function that converts each datarow of the results to the anonymous typed object, which is returned in a list. I actually haven't been able to figure out how to build a list of those objects manually.

Another Update: Using Reed Copsey's reply below, I created the list manually in a way that duplicates the list that I'm getting, and I can reproduce the error with the manually created list:

var objectList = Enumerable.Range(0, 5).Select(i => new { DecimalValue = (decimal)31.45, Id = 3 }).ToList();
var result = (objectList.Any()) ? objectList.Distinct().Sum(x => x.DecimalValue) : 0;

I also tried removing the cast to decimal, and the issue is still present.

Another Update: After some further debugging I realized something I've never come across before. I set a breakpoint immediately after the line of code I mentioned that was having problems in each case. For the workaround, it returned 31.45. For the problem line, it returned 0. When I stepped into the next line, and looked at the variable again, it said 31.45. The line I set the breakpoint on did not access or modify the variable.

It would seem that both lines work, but that the debugger showed that it did not until I moved at least two lines after the code. I've never come across that before, but it shows that the code indeed does work.

There is no problem with your statement.

The issue is elsewhere, most likely in how you're constructing objectList .

For example, the following works exactly as expected, and prints "0.6" (as would be expected):

namespace Test
{
    using System;
    using System.Linq;

    internal class TestCompile
    {
        private static void Main(string[] args)
        {
            var objectList = Enumerable.Range(0, 3).Select(i => new { ID = i, DecimalValue = i / 5.0m }).ToList();

            decimal result = objectList.Any() ? objectList.Distinct().Sum(x => x.DecimalValue) : 0;

            Console.WriteLine(result);
            Console.ReadKey();
        }
    }
}

Update:

In response to your update, this also works perfectly:

private static void Main(string[] args)
{
    var objectList = Enumerable.Range(0, 5).Select(i => new { DecimalValue = (decimal)31.45, Id = 3 }).ToList();
    var result = (objectList.Any()) ? objectList.Distinct().Sum(x => x.DecimalValue) : 0;

    Console.WriteLine(result);
    Console.ReadKey();
}

It is using the exact code you pasted, and reports 31.45 , as expected (due to the unique constraint). Note that, personally, I would use 31.45m instead of the cast, but it works even as written...

For what it's worth, your code works though I had to make up my own type.

[Test]
public void X()
{
    var objectList = Enumerable.Range(1, 10).Select(d => new {DecimalValue = Convert.ToDecimal(d)});

    var result = (objectList.Any()) ? objectList.Distinct().Sum(x => x.DecimalValue) : 0;

    Assert.AreEqual(55, result);
    Assert.AreEqual(typeof (decimal), result.GetType());
}

Too big for a comment so CW it is.

I just compiled a code

    public class ObjectValue
    {
        public Decimal DecimalValue { get; set; }
    }

    class Program
    {

        static void Main(string[] args)
        {
            var objectList = new List<ObjectValue>() { new ObjectValue() { DecimalValue = 5 }, new ObjectValue() { DecimalValue = 5 } ,
                    new ObjectValue() { DecimalValue = 5 }};


            var result = (objectList.Any()) ? objectList.Distinct().Sum(x => x.DecimalValue) : 0;

            decimal resultDecimal = 0;
            if (objectList.Any())
                resultDecimal = objectList.Distinct().Sum(x => x.DecimalValue);

        }
    }

And result and resultDecimal are 15 , in my case. I have coherent result in both cases provided, as I expected. So the error is somewhere else.

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