1
votes

I am new to C# and found a method I can't quite finish making work. The method is supposed to take an array and return it with all integers squared.

What I don't understand is the <long> return type or why it would be needed and the fact that if an item that is more than int's MaxValue is passed, then the method doesn't change it in any way when it's supposed to return it as 0.

What I want is if an array like new long[] {4294967296, 4295098369, 4611686014132420609} is passed to it, it would return {0, 0, 0}

using System;
using System.Collections.Generic;
using System.Linq;

namespace EnumerableTask
{
    public class EnumerableManipulation
    {
        public IEnumerable<long> GetSquareSequence(IEnumerable<int> data)
        {
        /// <summary>Transforms integer sequence to its square sequence
        /// <param name="data">Source int sequence.</param>
        ///   Returns sequence of squared items.
            foreach (int item in data)
            {
                if (item == null)
                {
                    yield return 0;
                }                
                else if (item > int.MaxValue)
                {
                    yield return 0;
                }
                yield return item * item;
///For some reason just returns an item's value if it's more than int.MaxValue. Why?
            }
        }
    }
}
3
int cannot have value greater then int.MaxValue, it will have some negative vaule because of overflow - 0lukasz0
The long return type is easy to explain: int.MaxValue squared doesn't fit in an int, but it does fit in a long. To actually perform the calculation so it yields a long, however, you have to convert the operand first: yield return (long) item * item. Note that the test for null is entirely useless and the compiler should have told you so: an int is never null. Nor is an int ever greater than int.MaxValue, by definition, so the whole thing can be simplified to just the yield. - Jeroen Mostert
Change input type to IEnumerable<long>. Otherwise, you will have overflow as now. - kosist
The highest int value that you can square, which fits in an Int32 is 46,340. Everything above that will overflow. - Steven

3 Answers

2
votes
if (item == null)

primitive types like int cannot be null, so this is redundant.

 else if (item > int.MaxValue)

An int cannot be larger than int.MaxValue. Perhaps you intended to tale a list of long? i.e. GetSquareSequence(IEnumerable<long> data) ? Otherwise you should not need that check.

When using any arithmetic operation on values you may run the risk of overflow, i.e. that the result is larger than the number of bits used to represent the value. This is especially an issue when multiplying large numbers. But since a long is twice as many bits, you should not need any overflow checking. So your whole code should be possible to replace with

foreach (long item in data)
{
    yield return item * item;
}

or just

var squared list = myList.Select(i => (long)i * i);

If you want to use the same return type as input type with overflow checking, you might want to use checked expressions to find such cases and handle them somehow.

1
votes

You have integer overflow on item * item, to prevent it cast item before multiplication:

// static : we don't want "this" here, so we can declare it as static 
public static IEnumerable<long> GetSquareSequence(IEnumerable<int> data)
{
    // the method is public we should validate user input
    if (data == null)
        throw new ArgumentNullException(nameof(data)); // or yield break;

    // long item  - we should multiply longs, not ints:
    // item is long; int.MaxValue * int.MaxValue < long.MaxValue   
    foreach (long item in data)
        yield return item * item; 
}

Please note, that both of your conditions are of no use: if (item == null) {...} will never be true (since int is struct and thus can't be null); if (item > int.MaxValue) will never be true since int value can't be beyond its own maximum value

0
votes

The item can not be larger than int.MaxValue because data type of item is int and the maximum value of int is exactly int.MaxValue.

If you want pass larger value than int you must use larger data type. Don't know your case in detail, but using IEnumerable<long> instead of IEnumerable<int> may be to solution for you.