I am fairly new to C# coming from Java, and I'm wondering if there's a simple way to avoid code repetition involving primitive types like this:
private Boolean AtLeastOneBufferItemIsNonZero(int[] Buffer)
{
Boolean result = false;
foreach (int Item in Buffer)
{
result = !(Item == (int)0);
if (result) break;
}
return result;
}
private Boolean AtLeastOneBufferItemIsNonZero(float[] Buffer)
{
Boolean result = false;
foreach (float Item in Buffer)
{
result = !(Item == (float)0);
if (result) break;
}
return result;
}
I can't find a "Number" supertype so that I can compare "Item" in 开发者_如何学Ca generics implementation (I wouldn't mind the performance penalty of boxing, although I understand that in .NET there is no such thing?):
//SOMETHING LIKE THIS?
private Boolean AtLeastOneBufferItemIsNonZero<T>(T[] Buffer) where T : NUMBERTYPE
{
Boolean result = false;
foreach (T Item in Buffer)
{
result = !(Item.Equals(0)); //Nope....
if (result) break;
}
return result;
}
Is the only way to create my own Number implementation and having a compare() method? That sounds like overkill doesn't it?
LINQ makes this pretty simple to do, by relying on the fact that the default value of any numeric type is zero, and they have appropriate equality methods:
private bool AtLeastOneBufferItemIsNonZero<T>(T[] items)
{
T zero = default(T);
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
return items.Any(t => !comparer.Equals(t, zero));
}
Now that doesn't restrict it to numeric types, but it does avoid repetition. You can go further, by generalizing it to IEnumerable<T>
and making it an extension method:
public static class Extensions
{
public static bool ContainsNonDefaultValue<T>(this IEnumerable<T> source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
T zero = default(T);
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
return items.Any(t => !comparer.Equals(t, zero));
}
}
You could restrict this to value types by changing the constraint to
where T : struct
but that would be a bit pointless IMO. With the change to use EqualityComparer<T>.Default
, you can also use the method to check whether any value in a reference type sequence is non-null.
EDIT: As a side note, another way of look at it is to reverse the condition:
return !items.All(t => comparer.Equals(t, zero));
It depends whether you're happier with the concept of "any of them is non-zero" or "they're not all zero" :)
private Boolean AtLeastOneBufferItemIsNonZero<T>(T[] Buffer)
{
Boolean result = false;
foreach (T Item in Buffer)
{
result = !Item.Equals(default(T)); //Yep!!!
if (result) break;
}
return result;
}
PS. Use Linq
精彩评论