Regarding efficiency, does anyone know if the compiler is clever enough to not create the array containing 1, 3, 5 for each iteration of the loop in the following code?
var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new[] { 1, 3, 5 }.Contains(i));
I prefer it for readability, but not at the sake of performance.
The answer is no it doesn't optimize out the allocation of the array
Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Predicate<int> <>9__0_0;
internal bool <M>b__0_0(int i)
{
// bam!
int[] obj = new int[3];
RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
return Enumerable.Contains(obj, i);
}
}
As #Michael Randall already wrote, it looks like it is not possible.
I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:
int[] a = null;
foo.RemoveAll(i => (a ?? (a = new[] { 1, 3, 5 })).Contains(i));
This is actually yours, with little un-beatuness of needing an external variable.
foo = foo.Except(new[] { 1, 3, 5 }).ToList();
That's actually pretty nice solution using Linq.
new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));
new[] {1, 3, 5}.Iterate(x => foo.Remove(x));
This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)
static class Extensions
{
public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
foreach (var item in source)
{
action.Invoke(item);
}
}
}
Since the compiler is not that smart, we must outsmart him.
var foo = new List<int> { 1, 2, 3, 4, 5 };
var bar = new HashSet<int>() { 1, 3, 5 };
foo.RemoveAll(i => bar.Contains(i));
Related
Is it possible to ignore order of elements in IEnumerable, like in Assert.That( ... , Is.EquivalentTo( ... ));, but using TestCaseData.Returns() in NUnit 3?
If I understand your question correctly, you want to write test cases in NUnit to determine whether two lists are of identical length and contain the same elements, ignoring the order of the elements.
If my interpretation of your question is correct then I have included an example below which should solve your problem:
[TestFixture]
public class MyTests
{
[TestCaseSource(typeof(MyDataClass), nameof(MyDataClass.TestCases))]
public bool ListEqualTest(IEnumerable<int> list1, IEnumerable<int> list2)
{
return list1.Intersect(list2).Count() == list1.Count() && list1.Count == list2.Count;
}
}
public class MyDataClass
{
public static IEnumerable TestCases
{
get
{
var list1 = new List<int> { 1, 2, 3, 4, 5 };
var list2 = new List<int> { 3, 4, 2, 1, 5 };
var list3 = new List<int> { 6, 7, 8, 9, 10 };
var list4 = new List<int> { 6, 7, 8, 11, 12 };
yield return new TestCaseData(list1, list2).Returns(true);
yield return new TestCaseData(list3, list4).Returns(false);
}
}
}
I adapted the example provided in the NUnit documentation, found here.
My solution obviously makes use of the primitive type int when defining the IEnumerable<int> parameters and constructing the List<int> objects but it won't take much effort at all to adapt it for your specific needs.
Hope this helps.
Consider this method
public static void NumberList(params int[] numbers)
{
foreach (int list in numbers)
{
Console.WriteLine(list);
}
}
I can call this method and supply seperated single integers or just one array with several integers. Within the method scope they will be placed into an array called numbers (right?) where I can continue to manipulate them.
// Works fine
var arr = new int[] { 1, 2, 3};
NumberList(arr);
But if I want to call the method and supply it arrays instead, I get an error. How do you enable arrays for params?
// Results in error
var arr = new int[] { 1, 2, 3};
var arr2 = new int[] { 4, 5, 6 };
NumberList(arr, arr2);
The type you're requiring is an int[]. So you either need to pass a single int[], or pass in individual int parameters and let the compiler allocate the array for you. But what your method signature doesn't allow is multiple arrays.
If you want to pass multiple arrays, you can require your method to accept any form that allows multiple arrays to be passed:
void Main()
{
var arr = new[] { 1, 2, 3 };
NumberList(arr, arr);
}
public static void NumberList(params int[][] numbers)
{
foreach (var number in numbers.SelectMany(x => x))
{
Console.WriteLine(number);
}
}
public void Test()
{
int[] arr1 = {1};
int[] arr2 = {2};
int[] arr3 = {3};
Params(arr1);
Params(arr1, arr2);
Params(arr1, arr2, arr3);
}
public void Params(params int[][] arrs)
{
}
Your method is only set to accept a single array. You could use a List if you wanted to send more than one at a time.
private void myMethod(List<int[]> arrays){
arrays[0];
arrays[1];//etc
}
You cant by langauge means.
However there is a way to work arround this by overlading the method something like this:
public static void NumberList(params int[][] arrays)
{
foreach(var array in arrays)
NumberList(array);
}
See here
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Let's say I have a class like this:
public class Fraction
{
int numerator;
int denominator;
public Fraction(int n, int d)
{
// set the member variables
}
// And then a bunch of other methods
}
I want to initialize an array of them in a nice way, and this post is a big list of approaches that are error prone or syntactically cumbersome.
Of course an array constructor would be nice, but there's no such thing:
public Fraction[](params int[] numbers)
So I'm forced to use a method like
public static Fraction[] CreateArray(params int[] numbers)
{
// Make an array and pull pairs of numbers for constructor calls
}
which is relatively clunky, but I don't see a way around it.
Both forms are error prone because a user could mistakenly pass an odd number of parameters, maybe because s/he skipped a value, which would leave the function scratching its head wondering what the user actually wanted. It could throw an exception, but then the user would need to try/catch. I'd rather not impose that on the user if possible. So let's enforce pairs.
public static Fraction[] CreateArray(params int[2][] pairs)
But you can't call this CreateArray in a nice way, like
Fraction.CreateArray({0,1}, {1,2}, {1,3}, {1,7}, {1,42});
You can't even do
public static Fraction[] CreateArray(int[2][] pairs)
// Then later...
int[2][] = {{0,1}, {1,2}, {1,3}, {1,7}, {1,42}};
Fraction.CreateArray(numDenArray);
Note that this would work just fine in C++ (I'm pretty sure).
You're forced to do one of the following instead, which is abhorrent. The syntax is terrible and it seems really awkward to use a jagged array when all the elements have the same length.
int[2][] fracArray = {new int[2]{0,1}, /*etc*/);
Fraction.CreateArray(fracArray);
// OR
Fraction.CreateArray(new int[2]{0,1}, /*etc*/);
Similarly, Python-style tuples are illegal and the C# version is icky:
Fraction.CreateArray(new Tuple<int,int>(0,1), /*etc*/);
The use of a pure 2D array might take the following form, but it's illegal, and I'm sure there's no legal way to express it:
public static Fraction[] CreateArray(int[2,] twoByXArray)
// Then later...
Fraction[] fracArray =
Fraction.CreateArray(new int[2,4]{{0,1}, {1,2}, {1,3}, {1,6}});
This doesn't enforce pairs:
public static Fraction[] CreateArray(int[,] twoByXArray)
OK, how about
public static Fraction[] CreateArray(int[] numerators, int[] denominators)
But then the two arrays might have different lengths. C++ allows
public static Fraction[] CreateArray<int N>(int[N] numerators, int[N] denominators)
but, well, this isn't C++, is it?
This sort of thing is illegal:
public static implicit operator Fraction[](params int[2][] pairs)
and unworkable anyway, again because of the abhorrent syntax:
Fraction[] fracArray = new Fraction[](new int[2]{0,1}, /*etc*/ );
This might be nice:
public static implicit operator Fraction(string s)
{
// Parse the string into numerator and denominator with
// delimiter '/'
}
Then you can do
string[] fracStrings = new string[] {"0/1", /*etc*/};
Fraction[] fracArray = new Fraction[fracStrings.Length];
int index = 0;
foreach (string fracString in fracStrings) {
fracArray[index] = fracStrings[index];
}
I don't like this approach for five reasons. One, the implicit cast unavoidably instantiates a new object, but we already have a perfectly good one, namely the one we're trying to initialize. Two, it can be confusing to read. Three, it forces you to do explicitly what I wanted to encapsulate in the first place. Four, it leaves room for bad formatting. Five, it involves one-time parsing of string literals, which is more like a practical joke than good programming style.
The following also requires wasteful instantiation:
var fracArray = Array.ConvertAll(numDenArray, item => (Fraction)item);
The following use of a property has the same problem unless you use those terrible jagged arrays:
public int[2] pair {
set {
numerator = value[0];
denominator = value[1];
}
}
// Then later...
var fracStrings = new int[2,4] {{0,1}, /*etc*/};
var fracArray = new Fraction[fracStrings.Length];
int index = 0;
foreach (int[2,] fracString in fracStrings) {
fracArray[index].pair = fracStrings[index];
}
This variation doesn't enforce pairs:
foreach (int[,] fracString in fracStrings) {
fracArray[index].pair = fracStrings[index];
}
Again, this approach is big anyway.
These are all of the ideas I know how to derive. Is there a good solution?
I can't think of an elegant, and at the same time memory efficient solution for array.
But there is an elegant solution for list (and similar) utilizing the C# 6 collection initializer feature:
public static class Extensions
{
public static void Add(this ICollection<Fraction> target, int numerator, int denominator)
{
target.Add(new Fraction(numerator, denominator));
}
}
With that extension method in place, you can easily initialize a Fraction list for instance:
var list = new List<Fraction> { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 7 }, { 1, 42 } };
And of course, although not memory efficient, you can use it to initialize Fraction array either:
var array = new List<Fraction> { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 7 }, { 1, 42 } }.ToArray();
or even making it more concise by declaring a list derived class with implicit array conversion operator:
public class FractionList : List<Fraction>
{
public static implicit operator Fraction[](FractionList x) => x?.ToArray();
}
and then use
Fraction[] array = new FractionList { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 7 }, { 1, 42 } };
You could create a fraction array builder with a fluent interface. It would lead to something like
public class FractionArrayBuilder
{
private readonly List<Fraction> _fractions = new List<Fraction>();
public FractionArrayBuilder Add(int n, int d)
{
_fractions.Add(new Fraction(n, d));
return this;
}
public Fraction[] Build()
{
return _fractions.ToArray();
}
}
which can be called using
var fractionArray = new FractionArrayBuilder()
.Add(1,2)
.Add(3,4)
.Add(3,1)
.Build();
which is an easy to understand statement.
I have made a fiddle to demonstrate.
The most succinct way I can think of for your particular example involves writing an implicit operator for the Fraction class:
public sealed class Fraction
{
public Fraction(int n, int d)
{
Numerator = n;
Deniminator = d;
}
public int Numerator { get; }
public int Deniminator { get; }
public static implicit operator Fraction(int[] data)
{
return new Fraction(data[0], data[1]);
}
}
Then you can initialise it like this:
var fractions = new Fraction[]
{
new [] {1, 2},
new [] {3, 4},
new [] {5, 6}
};
Unfortunately you still need the new [] on each line, so I don't think this gains very much over the normal array initialisation syntax:
var fractions = new []
{
new Fraction(1, 2),
new Fraction(3, 4),
new Fraction(5, 6)
};
I suppose you could write a "local" Func<> with a short name to simplify the initialisation somewhat:
Func<int, int, Fraction> f = (x, y) => new Fraction(x, y);
var fractions = new []
{
f(1, 2),
f(3, 4),
f(5, 6)
};
The drawback is that you'd need to add that extra line (initialising a Func<>) wherever you wanted to initialise the array - or have a private static method in the class instead - but then that method would be in scope throughout the class, which isn't ideal if it has a single-letter name.
However, the advantage of this approach is that it is very flexible.
I toyed with the idea of calling the inline function _, but I'm really not sure about that...
Func<int, int, Fraction> _ = (x, y) => new Fraction(x, y);
var fractions = new []
{
_(1, 2),
_(3, 4),
_(5, 6)
};
What are the ways to check if X exists in X,Y,Z in c#?
For eg:
X=5;
I want to check if X's value matches any of the comma separated values..
if(x in (2,5,12,14)
new int[] { 2,5,12,14}.Contains(x);
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
list.Contains(5);
You may use .Contains method. e.g. listItems.Contains(x)
There is no in operator in C#, but you can implement an extension method to make the code more readable.
public static class Ext
{
public static bool In<T>(this T val, params T[] values) where T : struct
{
return values.Contains(val);
}
}
//usage: var exists = num.In(numbers);
Linq.Contains() what you searching for
// Create List with three elements.
var list = new List<string>();
list.Add("cat");
list.Add("dog");
list.Add("moth");
// Search for this element.
if (list.Contains("dog"))
{
Console.WriteLine("dog was found");
}
There are two methods Linq.Contains() method and an extension Linq.Contains<int>
var list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Use extension method.
var stp = new Stopwatch();
stp.Start();
bool a = list.Contains<int>(7);
stp.Stop();
Console.WriteLine("Time in extenstion method {0}", stp.Elapsed);
stp.Restart();
// Use instance method.
bool b = list.Contains(7);
stp.Stop();
Console.WriteLine("Time in normal method {0}", stp.Elapsed);
Performance benchmark : The version specific to List i.e, list.Contains(7); , found on the List type definition, is faster. I tested the same List with the two Contains methods.
Let's say I for example have this class that generates Fibonacci numbers:
public class FibonacciSequence : IEnumerable<ulong>
{
public IEnumerator<ulong> GetEnumerator()
{
var a = 0UL;
var b = 1UL;
var c = a + b;
while (true)
{
yield return c;
c = a + b;
a = b;
b = c;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I can then write a test that makes sure that the n first numbers in the sequence are correct.
[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
var sequence = new FibonacciSequence().Take(15).ToArray();
CollectionAssert.AreEqual(sequence, new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}
When I check for coverage however, I will see that the IEnumerable.GetEnumerator() method is untested, and my coverage will be lower than it really needs to be. Fair enough. But how should I test that method?
How do you usually deal with this?
EDIT: Updated based on what Marc said.
Well you could get the coverage up by doing:
// Helper extension method
public static IEnumerable AsWeakEnumerable(this IEnumerable source)
{
foreach (object o in source)
{
yield return o;
}
}
...
[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
IEnumerable weak = new FibonacciSequence().AsWeakEnumerable();
var sequence = weak.Cast<int>().Take(15).ToArray();
CollectionAssert.AreEqual(sequence,
new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}
Note that weak is declared to be the nongeneric IEnumerable type... which means you need to call Cast on it to cast each returned object to int.
I'm not sure I'd bother though...
You would have to use use IEnumerable (non-generic); I posted a reply using Cast<T>, but that will still cheat (it checked for the desired type as a special case) - you might need something like:
public static int CountUntyped(this IEnumerable source) {
int count = 0;
foreach(object obj in source) { count++; }
return count;
}
IEnumerable<T> source = ...
Assert.AreEqual(typed.Count(), source.CountUntyped());
I wouldn't test it. I would try to filter the method out of the coverage tool. I think coverage should check things I want to have covered and not everything. From other comments you seem to be using TestDriven.Net. I don't know how well that filters but it was possible with NCover. You could try PartCover also.