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?
}
}
}
}
CodePudding user response:
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.
CodePudding user response:
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
CodePudding user response:
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.