Enumerator behavior changes based on how we reference it? - c#

Wrapping a reference to the list's enumerator inside a class seems to change its behavior. Example with an anonymous class:
public static void Main()
{
var list = new List<int>() { 1, 2, 3 };
var an = new { E = list.GetEnumerator() };
while (an.E.MoveNext())
{
Debug.Write(an.E.Current);
}
}
I would expect this to print "123", but it only prints zero and never terminates. The same example with a concrete class:
public static void Main()
{
var list = new List<int>() { 1, 2, 3 };
var an = new Foo()
{
E = list.GetEnumerator()
};
while (an.E.MoveNext())
{
Debug.Write(an.E.Current);
}
}
public class Foo
{
public List<int>.Enumerator E { get; set; }
}
What's going on?

I tested it and for me it does not work with your concrete class either.
The reason is that List<T>.Enumerator is a mutable struct and an.E is a property.
The compiler generates a backing field for each auto-property like this:
public class Foo
{
private List<int>.Enumerator _E;
public List<int>.Enumerator get_E() { return E; }
public void set_E(List<int>.Enumerator value) { E = value; }
}
A struct is a value-type, so every-time you access an.E you get a copy of that value.
When you call MoveNext() or Current, you call it on that copy and this copy is mutated.
The next time you access an.E to call MoveNext() or Current you get a fresh copy of the not-yet-iterated enumerator.
And an.E.Current is 0 instead of 1 because - again - you get a fresh enumerator that MoveNext() was not yet called upon.
If you want to store a reference of the list's enumerator you could declare your class Foo with a property of type IEnumerator<int>:
public class Foo
{
public IEnumerator<int> E { get; set; }
}
If you assign E = list.GetEnumerator(); now, the enumerator gets boxed and a reference instead of a value is stored.

Related

Call one method with parent class instead of two with childs

I have classes:
public class Throw
{
public double speed { get; set; }
public double accurency { get; set; }
}
public class FastThrow : Throw{}
public class LowThrow : Throw{}
Instead of having:
public static FastThrow SetFastThrow(List<object> args)
{
return new FastThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
public static LowThrow SetLowThrow(List<object> args)
{
return new LowThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
I want to have one with parent class:
public static Throw SetThrow(List<object> args)
{
return new Throw
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
To declare list or some other generic interface with child class with instance of parent class. Then adding new elements to existing collection. I know that below example has compilation errors, but it should look like:
List<List<object>> firstList = new List<List<object>>();
public void Main()
{
IList<FastThrow> secondList = new List<Throw>();
foreach (var item in firstList)
{
secondList.Add(SetThrow(item));
}
}
I read about contravariance and do not know if this is possible.
You can't. Rahter than
To declare list or some other generic interface with child class with
instance of parent class.
you should
To declare list or some other generic interface with parent class with
instance of chidlren class.
The second way, as Anirban said, use generic classes, refactor your SetThrow method as following:
public static T SetThrow<T>(List<object> args) where T : Throw, new()
{
return new T
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
So that you can use SetThrow method only to generate different kinds of classes as long as they are child classes. e.g:
IList<FastThrow> secondList = new List<FastThrow>();
foreach (var item in firstList)
{
secondList.Add(SetThrow<FastThrow>(item));
}
And generic classes are strong typed and elegant to use.

C# - How can I access the value using properties of classes in an override method?

My Code:
public class A
{
public virtual void displayDetailInfo()
{
}
}
public class B : A
{
public String _a;
public int _n;
public B() { }
public B(String _a, int _n)
{
this._a = _a;
this._n = _n;
}
public String A
{
get { return _a; }
set { this._a = value; }
}
public int N
{
get { return _n; }
set { this._n = value; }
}
public override void displayDetailInfo()
{
Console.WriteLine(A);//To obtain value entered in Main(i.e. f.A)
Console.WriteLine(N);//To obtain value entered in Main(i.e. f.N)
}
}
public class Program
{
public static void Main(String[] args)
{
A v = new A();
A v1 = new B();
B f = new B();
f.A = Console.ReadLine(); //Value to be accessed
f.N = Convert.ToInt32(Console.ReadLine()); //Value to be accessed
v1.displayDetailInfo();
}
}
How can I get the value(f.A and f.N) I entered in Main accessed from the overrided method in class B(i.e. displayDetailInfo()). The code I wrote doesn't obtains any value(i.e. Console.WriteLine(A) gives no value of f.A). So how can I get the value of f.A and f.N from overrided displayDetailInfo()?
Whenever you use new to create a new object, you are creating a new, independent object that has its own state.
Here, you are creating 3 separate objects - v, v1, f.
A v = new Vehicle();
A v1 = new B();
B f = new B();
Changing a property of one of these objects does not affect the properties of the other two objects whatsoever.
Here you change the properties of f, but the properties of v1 is not affected.
f.A = Console.ReadLine();
f.N = Convert.ToInt32(Console.ReadLine());
This is why when you call v1.displayDetailInfo(), it prints null and 0. null and 0 are the default values of string and int respectively. v1's properties have not been set yet, so they hold the default values.
To fix this, just call f.displayDetailInfo() instead.
You can't do this because you v1 is a different instance of B than the one you want to get the values from (f)
Calling f.displayDetailInfo() should give you the result you want
You are setting A of a different object than what you are calling displayDetailInfo on.
I think you meant to do this:
public static void Main(String[] args)
{
A v = new Vehicle();
B v1 = new B();
v1.A = Console.ReadLine(); //Value to be accessed
v1.N = Convert.ToInt32(Console.ReadLine()); //Value to be accessed
v1.displayDetailInfo();
}
It's not possible for v1 to have data you entered in f. The class is just a blueprint, v1 and f are different instances that exist in different parts of the heap.
v1.A is not the same as f.A and v1.N is not the same as f.N
To see the values you entered, you better call:
f.displayDetailInfo()
Also, you're using properties wrong. If you want to use backing fields, the ones with the underscores (_n and _a), you better make them private. And unless you want to have additional logic to the getters or setters you are better off not using backing fields altogether and use auto implemented properties:
public string A { get; set; }
public string N { get; set; }

Selecting Items using a HashSet C#

I have a HashSet. Is there a method that can utilize the IEqualityComparer for retrieving items where you pass in an object that will satisfies the equals method defined in the IEqualityComparer?
This might explain it a bit more.
public class Program
{
public static void Main()
{
HashSet<Class1> set = new HashSet<Class1>(new Class1Comparer());
set.Add( new Class1() { MyProperty1PK = 1, MyProperty2 = 1});
set.Add( new Class1() { MyProperty1PK = 2, MyProperty2 = 2});
if (set.Contains(new Class1() { MyProperty1PK = 1 }))
Console.WriteLine("Contains the object");
//is there a better way of doing this, using the comparer?
// it clearly needs to use the comparer to determine if it's in the hash set.
Class1 variable = set.Where(e => e.MyProperty1PK == 1).FirstOrDefault();
if(variable != null)
Console.WriteLine("Contains the object");
}
}
class Class1
{
public int MyProperty1PK { get; set; }
public int MyProperty2 { get; set; }
}
class Class1Comparer : IEqualityComparer<Class1>
{
public bool Equals(Class1 x, Class1 y)
{
return x.MyProperty1PK == y.MyProperty1PK;
}
public int GetHashCode(Class1 obj)
{
return obj.MyProperty1PK;
}
}
If you want to retrieve items based on a single property, you might want to use a Dictionary<T,U> instead of a hashset. You can then place the items within the dictionary, using MyProperty1PK as the key.
Your query then becomes simple:
Class1 variable;
if (!dictionary.TryGetValue(1, out variable)
{
// class wasn't in dictionary
}
Given that you're already storing using a comparer which only uses this value as the uniqueness criteria, there is really no disadvantage to just using that property as the key in a dictionary instead.

Delegate to an instance method cannot have null 'this'

Say I have a class declared as follows:
public class ExampleClass
{
public Action<int> Do { get; set; }
public ExampleClass()
{
}
public void FuncA(int n)
{
//irrelevant code here
}
public void FuncB(int n)
{
//other irrelevant code here
}
}
I want to be able to use this class like this
ExampleClass excl = new ExampleClass() { Do = FuncA }
or
ExampleClass excl = new ExampleClass() { Do = excl.FuncA }
or
ExampleClass excl = new ExampleClass() { Do = ExampleClass.FuncA }
I can compile the second option there, but I get a "Delegate to an instance method cannot have null 'this'." exception when I hit that code. The third one doesn't even make sense, because FuncA isn't static.
In my actual code, there will be maybe 10-15 different functions it could get tied to, and I could be adding or removing them at any time, so I don't want to have to have a large switch or it-else statement. Additionally, being able assign a value to 'Do' when instantiating the class is very convenient.
Am I just using incorrect syntax? Is there a better way to create a class and assign an action in one line? Should I just man up and manage a huge switch statement?
You have to create the instance of the class and later set the property to the instance member. Something like:
ExampleClass excl = new ExampleClass();
excl.Do = excl.FuncA;
For your line:
ExampleClass excl = new ExampleClass() { Do = FuncA }
FuncA is not visible without an instance of the class.
For:
ExampleClass excl = new ExampleClass() { Do = excl.FuncA }
Instance has not yet been created that is why you are getting the exception for null reference.
For:
ExampleClass excl = new ExampleClass() { Do = ExampleClass.FuncA }
FuncA is not a static method, you can't access it with the class name.
In object initializer syntax you cannot access the variable being initialized before it is definitely assigned:
ExampleClass excl = new ExampleClass()
{
Do = excl.FuncA //excl is unavailable here
}
Read Object and Collection Initializers (C# Programming Guide) for more info.
You could do the following, for example:
public class ExampleClass
{
public Action<int> Do { get; set; }
public ExampleClass(bool useA)
{
if (useA)
Do = FuncA;
else
Do = FuncB;
}
public void FuncA(int n)
{
//irrelevant code here
}
public void FuncB(int n)
{
//other irrelevant code here
}
}
and use it:
ExampleClass exclA = new ExampleClass(true);
ExampleClass exclB = new ExampleClass(false);
Another idea is if these functions may be declared as static (i.e. they don't need any instance members of the ExampleClass), then this would work:
public class ExampleClass
{
public Action<int> Do { get; set; }
public ExampleClass() { }
public static void FuncA(int n) { /*...*/}
public static void FuncB(int n) { /*...*/}
}
and use it the way you want:
ExampleClass excl = new ExampleClass() { Do = ExampleClass.FuncA };
If you have extension methods make sure that those values are not null before invoking the extension methods or handle nulls inside the extension methods.
For example
public static ExtensionClass
{
public static bool RunExtensionMethod(this object myObject)
{
var someExecutionOnMyObject = myObject.IsValid();
//the above line would invoke the exception when myObject is null
return someExecutionOnMyObject ;
}
}
public void CallingMethod()
{
var myObject = getMyObject();
if(myObject.RunExtensionMethod()) //This would cause "delete to an instance method cannot have null" if myObject is null
{
}
}
To handle this scenario handle nulls and assert nulls if you own the extension class.
public static ExtensionClass
{
public static bool RunExtensionMethod(this object myObject)
{
if(myObject == null) throw new ArgumentNullException(nameof(myObject));
var someExecutionOnMyObject = myObject.IsValid();
return someExecutionOnMyObject ;
}
}
public void CallingMethod()
{
var myObject = getMyObject();
if(myObject != null && myObject.RunExtensionMethod())
{
}
}

Delegate is a pointer to a function? And also saves variables?

As far as I understand the concept of delegates, they simply point to a method. Then when I'm feeling lucky I can go out and invoke the method my delegate is pointing to, right?
Given is the following code:
class Program
{
static void Main(string[] args)
{
Func<MyClass> myAct = GetAct();
Method(myAct);
}
private static Func<MyClass> GetAct()
{
MyClass obj = new MyClass()
{
Prop1 = 5
};
Func<MyClass> myAct = new Func<MyClass>(
() =>
{
MyClass obj2 = new MyClass();
MyClass2 obj3 = new MyClass2()
{
Prop3 = 25,
Prop4 = "test"
};
obj2.Prop2 = ((obj.Prop1 + 5) * obj3.Prop3)
.ToString() + obj3.Prop4;
return obj2;
});
return myAct;
}
static void Method(Delegate func)
{
GC.Collect();
GC.WaitForPendingFinalizers();
var result = func.DynamicInvoke();
}
}
class MyClass
{
public int Prop1 { get; set; }
public string Prop2 { get; set; }
}
class MyClass2
{
public int Prop3 { get; set; }
public string Prop4 { get; set; }
}
Now my delegate myAct (in this case a Func<MyClass>) is pointing to an anonymous function which performs some simple assignation of variables. Nothing special so far.
We invoke the delegate.
Everything went fine, just as we expected. But the question is why? If the delegate just simply points to the anonymous method AND a garbage collection was done, how could the CLR know what obj and it's values are?
Where is the reference to obj stored, to be available when the function is called? Inside the delegate?
Your anonymous method is defined within the scope of GetAct() so CLR makes scope variables available to the anonymous method.
It's similar to how an instance variable is usable by member methods.
Also, review the pitfalls of using closures: http://msmvps.com/blogs/peterritchie/archive/2010/11/03/deep-dive-on-closure-pitfals.aspx

Categories