Getting errors Working with HashSet - c#

I have created a class that contains a HashSet to keep track of integer numbers from 1-10. I used the Contain method to check if a value is inserted in the HashSet, with a bool. Here is my code:
class BasicIntSet
{
HashSet<int> intTest = new HashSet<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
bool has4 = intTest.Contains(4); // Returns true
bool has11 = intTest.Contains(11); // Returns false
bool result = intTest.IsSupersetOf(new[] { 4, 6, 7 });
}
My problem now is, that I get an error that says "Error 1 A field initializer cannot reference the non-static field, method, or property"
Does anybody know what I'm doing wrong?

All your code is in the class declaration... you're declaring instance fields. You can't make one instance field initializer refer to another (or refer to this in any other way), hence the error.
Fixing it is simple - put your code into a method:
using System;
using System.Collections.Generic;
class BasicIntSet
{
static void Main()
{
HashSet<int> intTest = new HashSet<int> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Console.WriteLine(intTest.Contains(4)); // True
Console.WriteLine(intTest.Contains(11)); // False
Console.WriteLine(intTest.IsSupersetOf(new[] { 4, 6, 7 })); // True
}
}
Note that your original error has nothing to do with HashSet<T> at all. Here's just about the simplest example I can think of:
class BadFieldInitializers
{
int x = 10;
int y = x;
}
That gives the same error - because again, one field initializer (for y) refers to this implicitly.

Related

Ignore order of elements in IEnumerable

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.

C# Why does the argument array has to be passed with the modifier ref if arrays are passed by reference?

I do not understand why this function was written like that:
System.Array.Resize<int>(ref int[], int)
If arrays are passed by reference by default
why wasn't it written like that:
System.Array.Resize<int>(int[], int)
This is because when we write a variable to a reference type object, there are kind of 2 parts, the actual object instance, and the reference which the variable name represents (32bit or 64bit memory address pointer internally, platform dependant). You can see that clearly with this sharplab.io snippet.
When we call a method, this pointer is copied, but the instance isn't, so:
var a = new Blah {Prop = "1"}; // Blah is a class, a reference type
Method(a);
void Method(Blah blah)
{
blah.Prop = "2"; // changes the shared instance, we know this.
blah = new Blah {Prop = "3"}; // has no effect.
}
Console.WriteLine(a.Prop); // 2
You see when we set blah inside of the method, we are mutating our local reference, not the shared one. Now if we use the ref keyword:
var a = new Blah {Prop = "1"};
Method(ref a);
void Method(ref Blah blah)
{
blah.Prop = "2"; // changes the shared instance, we know this.
blah = new Blah {Prop = "3"}; // now changes ref a outside
}
Console.WriteLine(a.Prop); // 3!
because the parameter blah is passed by reference, when we mutate it, we mutate the original reference a.
Arrays are indeed reference types, which means that changes done to the passed-in array object inside a method will be reflected on the caller's side:
public static void Foo(int[] a) {
a[0] = 1;
}
// ...
int[] a = new int[1];
Foo(a);
Console.WriteLine(a[0]); // 1
However, if you set the array to something else inside the method:
public static void Foo(int[] a) {
a = null;
}
// ...
int[] a = new int[1];
Foo(a);
Console.WriteLine(a[0]); // will not throw NRE
Declaring the parameter as ref will allow reassignments to the parameter to reflect on the caller's side.
Changing the size of the array requires creating a new array and hence re-assigning the parameter. You can't resize an array by mutating an existing array object somehow. This is why it needs to be declared as ref.
Simply speaking if your array is passed to a method as a ref parameter it can be replaced as a whole with another array created within the method.
It's not the case with arrays passed without ref keyword.
Code below illustrates the difference.
Note that individual elements of array parameters can be replaced in both cases (with of without ref keyword).
class Program
{
static void PrintArr(string comment, int[] arr)
{
Console.WriteLine($"{comment}:");
Console.WriteLine(string.Join(", ", arr.Select(e => e.ToString())));
}
static void NoRef(int[] arr)
{
int[] localArr = { 2, 4, 8, 10 };
arr = localArr;
}
static void ByRef(ref int[] arr)
{
int[] localArr = { 2, 4, 8, 10 };
arr = localArr;
}
static void Main()
{
int[] arr;
arr = new int[] { 1, 3, 4, 7, 9 };
PrintArr("Before NoRef is called", arr);
NoRef(arr);
PrintArr("After NoRef is called", arr);
PrintArr("Before ByRef is called", arr);
ByRef(ref arr);
PrintArr("After ByRef is called", arr);
Console.ReadLine();
}
}
}
Output for the code is shown below (note that ByRef method code replaced the array.
Before NoRef is called:
1, 3, 4, 7, 9
After NoRef is called:
1, 3, 4, 7, 9
Before ByRef is called:
1, 3, 4, 7, 9
After ByRef is called:
2, 4, 8, 10

List<T>.RemoveAll() efficiency / compiler optimisation

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));

What is C# equivalent of TSQL's "IN" operator? What are the ways to check if X exists in X,Y,Z in c#?

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.

How to check if an item is equal to any item in an array?

For instance, if I had an int[5] array = {1, 2, 3, 4, 5}
and an int check = 5
Is there an easy way to check if (check == any item in array) then do something?
Just use the Contains LINQ method. You'll need to add using System.Linq to access the method.
if(array.Contains(5))
{
//TODO do stuff
}
You can use Enumerable.Contains() method. This method returns true if the source sequence contains an element that has the specified value; otherwise, false.
Determines whether a sequence contains a specified element by using
the default equality comparer.
int[] array = {1, 2, 3, 4, 5};
if(array.Contains(5))
{
Console.WriteLine("Array has an element called 5");
}
Here is a DEMO.
Dont forget to add System.Linq namespace.
NOTE: Positive side of Contains() method, the enumeration is terminated as soon as a matching element is found. If you search the element like;
foreach(var i in array)
{
if(i == 5)
///
}
You have to enumerate all elements in array. I think this is biggest benefit of this method in this situation.
if (array.Contains(check))
{
//code
}
You can say:
array.Contains(check)
You can try this code:
int[] array = { 1, 2, 3, 3, 5 };
int check = 5;
int r = Array.Find<int>(array, (arr => arr == check));
if (r != 0)
{
// then do something.
}

Categories

Resources