C#: Custom IEnumerator? - c#

This is a message pertaining to C# in Unity, but I'm assuming general C# knowledge will apply.
Take the following code:
class myClass
{
IEnumerator myEnumerator;
public IEnumerator theEnumerator()
{
int i = 0;
while (true)
{
Debug.Log(i++);
yield return null;
}
}
public void Update()
{
if (myEnumerator == null) { myEnumerator = theEnumerator(); }
myEnumerator.MoveNext();
}
}
If I instance that class, then call "Update" once per frame, I get the following output in the log:
0
1
2
3
4...
That works fine, however I want to implement some custom functionality in the IEnumerator itself. But if I create the following:
public class myIEnumerator : IEnumerator
{
public int myCustValue;
public void myCustFunction(){}
}
and then update the oringal class, replacing "IEnumerator" the "myIEnumerator", I get the following error:
The body of `myClass.theEnumerator()' cannot be an iterator block because `myIEnumerator ' is not an iterator interface type
What am I doing wrong here, and how can I make my own custom IEnumerator?

You can only use yield within a method whose return type is IEnumerator, IEnumerable, IEnumerator<T>, or IEnumerable<T>. You can't change the return type of the method to a type that implements one of those interfaces, that doesn't make sense.
The reason for this is that the C# compiler generates a special class that implements one of those 4 interfaces (actually it implements both IEnumerator and IEnumerable or the generic versions thereof) and an instance of that compiler generated class is what actually gets returned from the method. By changing the return type you're trying to say that the compiler will create an instance of your class that will do the enumeration. But it can't do that, because it doesn't actually know anything about your class (and in fact your class might not even enumerate correctly).

I'm not familiar with Unity but I think you have to implement the IEnumerator interface. The methods MoveNext()and Reset()are missing.
Have a look at the IEnumerator Interface

Related

Implement a generic type to pass around

I am sure this is duplicate but I am not sure I am searching for the correct answers. Or understanding that it answers my question.
For 1 I think I am using my interface wrong. For 1 I break the rules of SOLID and am trying to clean it up. For example IReelWindow. I have things in there specific to ReelWindowTumble that the other ReelWindows don't use and throw not implemented errors. I started breaking it up into multiple interfaces but found i no longer had access to functions for ReelWindowTumble, even though I created a new interface for ITumble and still inherited from IReelWindow. The problem is in the functional code.
public interface IReelWindow
{
//stuff declared
void PopulateWindowTumble();
void PopulateWindow(int[] currentStops);
}
public class ReelWindow : IReelWindow
{
// implements most of it throwing exceptions when I don't use it.
public void PopulateWindow(int[] currentStops)
{
}
public void PopulateWindowTumble()
{
throw new NotImplementedException();
}
}
public class ReelWindowTumble : IReelWindow
{
// implements most of it throwing exceptions when I don't use it.
public void PopulateWindow(int[] currentStops)
{
}
void PopulateWindowTumble()
{
}
}
public class ReelWindowIndependent : IReelWindow
{
// implements most of it throwing exceptions when I don't use it.
public void PopulateWindow(int[] currentStops)
{
}
public void PopulateWindowTumble()
{
throw new NotImplementedException();
}
}
Here I declare a new IReelWindow and create a new ReelWindow based on client input. This works ok, as I just pass IReelWindow everywhere I want to use a ReelWindow.
I don't think this is the proper usage of my interface. If I use ICloneable, i don't declare a new object of ICloneable and pass it around.
But my intention is to create a Generic ReelWindow Type. I don't care what type of window the client creates. I just want to enforce what functions it should have as I use them specifically.
How do I declare a Generic ReelWindow that I can pass around without creating multiple functions that are identical but have strong types passed in?
public static IReelWindow CreateReelWindow(WindowType userSelectedWindowType, Paytable paytable)
{
IReelWindow _reelWindow;
if (userSelectedWindowType == WindowType.Standard)
{
_reelWindow = new ReelWindow(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop);
}
else if (userSelectedWindowType == WindowType.Tumble)
{
_reelWindow = new ReelWindowTumble(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop);
}
else if (userSelectedWindowType == WindowType.Independent)
{
_reelWindow = new ReelWindowIndependent(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop, paytable.ReelLengths, paytable.ReelStarts);
}
else
throw new ApplicationException("Unknown window type selected by user. Cannot continue.");
return _reelWindow;
}
Later in my code I use the reelwindows, and only pass in 'IReelWindow' as I don't care what type of reelwindow, the function will use it accordingly.
public abstract class AEval
{
public abstract double Evaluate(IReelWindow reelWindow, ref string flags, int currentStopsWeight);
public abstract double EvaluateVerbose(IReelWindow reelWindow, ref string flags, int currentStopsWeight);
}
The object that you are passing around is _reelWindow and while it implements IReelWindow, it is not an IReelWindow object. Instead it is one of your derived types: ReelWindow, ReelWindowTumble, ReelWindowIndependent, etc. Each of those derived types should be treated the same by your client (as you noted).
Let's pretend ReelWindow implements 2 methods from the interface, ReelWindowTumble implements 3 methods from the interface, and ReelWindowIndependent implements 10 methods from the interface. And the interface has a maximum of 10 methods to implement.
Using the language of your example, that means that ReelWindow will have 8 methods with NotImplementedException (NIE), ReelWindowTumble will have 7 methods NIE, and ReelWindowIndependent has 0 methods NIE.
What about your client code? Well, for all of this to make sense your client code should be calling all 10 of the interface methods while working with _reelWindow. That also means, using my example, that ReelWindowIndependent should work just fine with the client code because it has no NIE methods.
I'd say that your real problem is the NIE's. Remove those exceptions and instead return null. Then, in your client code, during flow of control, you can add statements to the effect of "if returned object is null, skip this section".
Remember, all objects inherit from 'object'. Those strongly typed return objects in your interface can be returned as 'object' too. That means any strongly typed object can be set to null. To repeat: try returning null value for methods with strongly typed return values and handling the null in your client code. Now, if the interface method has no return - it is marked void - then you don't need to worry about checking for null in your client code, nor would you need NIE: the method can be left blank and when called literally does nothing. If you ponder this, you might strive for interface design that does not use strongly typed return values. And that goes to Jamiec's comment: we need to know more about the interface.

Error trying to cast to generic type: redundant cast

I'm having a generic function that returns a new instance of a subclass of AnyListVM implemented basically like this:
public TListVM MakeListVM<TListVM>()
where TListVM : AnyListVM
{
TListVM listVM;
switch(typeof(TListVM).ToString())
{
case nameof(EventListVM):
listVM = new EventListVM();
// some more init stuff
break;
// some more similar cases
default:
throw new NotImplementedException();
}
return listVM;
}
The two involved classes look currently like that, without any meaningful implementation yet:
public abstract class AnyListVM
{
}
public class EventListVM : AnyListVM
{
}
Now Visual Studio underlines my new EventListVM() and nags that it can't implicitly convert EventListVM to TListVM.
Okay, so I thought I simply add an explicit cast:
listVM = (TListVM)new EventListVM();
But nope. Now Visual Studio underlines it again and says that it's a redundant cast. The offered automatic fix would be to remove the cast again. Infinite loop.
What is going wrong here, why am I not allowed to do this cast, explicitly or implicitly?
There's one glaring thing in your implementation that is incorrect, which other's have pointed out but haven't addressed satisfactorily. If you intend to instantiate TListVM, then you need to change two very important parts. First the new code listing:
public TListVM MakeListVM<TListVM>()
where TListVM : AnyListVM, new()
{
TListVM listVM = new TListVM();
EventListVM evtList = listVM as EventListVM;
if (evtList != null)
{
// set evtList properties. You can't change
// the instantiation method.
}
// repeat for other constructs.
return listVM;
}
Now, to expound a bit. The generic where clause needs to specify that you intend to create the TListVM with a parameterless constructor. To do that, you need to specify new() as a generic constraint.
This greatly simplifies your implementation which only knows there is something called TListVM that has a base class of AnyListVM and has a constructor with no parameters. There's no need for a complicated switch statement, or using the Activator.
Any time you are dealing with generics, work with your generic parameter directly.
Based on further information, the switch statement is still the wrong tool. Generics necessarily constrain how you work with your object. You can't change the constructor, but you can specialize how you set properties after the object is instantiated.
Above I changed the listing to show how to set those properties directly.
If, instead you were dead set on having different constructors, etc. then you would have to approach it differently. You would have to return the base class and not TListVM.
public AnyListVM MakeListVM<TListVM>()
where TListVM : AnyListVM
{
return MakeListVM(typeof(TListVM)) as TListVM;
}
private AnyListVM MakeListVM(Type listVM)
{
AnyListVM listVM;
switch(listVM.ToString())
{
case nameof(EventListVM):
listVM = new EventListVM();
// some more init stuff
break;
// some more similar cases
default:
throw new NotImplementedException();
}
return listVM;
}
The generic helper method lets you wrap your more generic factory method so it has the signature you want, without causing compile errors.
You can't guarantee that EventListVM will convert to TListVM as according to your generic restriction, one is allowed to pass ANY inherited class of AnyListVM, which may or may not be EventListVM. Example, if the caller of this method did this:
AnyListVM vm = MakeListVM<SomeOtherListVMConcrete>();
It would fail, but shouldn't.
I believe what you really want is to cast your EventListVM to AnyListVM, the actual base type rather than the generic.
AnyListVM listVM = new EventListVM();
Still, if you are always returning an instance of EventListVM, I'd consider removing the generic clause all together and updating the signature to have a return type of EventListVM.
To make your problem more obvious, consider a base class and two children:
public class Base { } //AnyListVM
public class Child1 : Base{ } //EventListVM
public class Child2 : Base{ } //OtherListVM
now your method looks like:
public T Get<T>() where T : Base
{
//code
T item = new Child1();
//more code
}
Imagine I send in Child2, which is perfectly valid from the method signature. The method's code now looks like:
Child2 item = new Child1();
which of course is going to be invalid at compile time.

Declare a function supporting both Void and IEnumerator

I was wondering if there is a way to declare a method (in an interface for example) that supports the use of IEnumerator and Void, without the need to implement both in the subclasses?
public void Start()
public IEnumerator Start()
this is related to my other question: Hold or Wait while Coroutine finishes
i noticed in the Unity context, the default Start() method seems to allow for both.
You can't do that because those methods would have the same signature and the CSC woudn't be able to figure out which method should be statically bound for each call. e.g.:
public class TestClass
{
public int FooMethod()
{
return 1;
}
public void FooMethod()
{
return;
}
public string FooMethod()
{
return "foo";
}
}
static void Main()
{
TestClass test = new TestClass();
Console.WriteLine(test.FooMethod()); // which FooMethod should be called here?
}
A method's return type is not considered as part of its signature. What you can do is overload the same method with a different signature to return a different type. Also, in the case of an additional method that differs only in returning void, you can always choose not to use the result returned by the original method.
The case with interfaces is similar. when a class implements an interface it is agreeing to a protocol, that it implements that interface's behaviour which is what consumers of your class expect. So you cannot partly agree with an interface. Although you can throw a NotImplementedException in your implementations you have to at least define all members, which leads to the same problem mentioned in the above example: the C# compiler will not be able to statically bind your method calls and your code will fail to compile.
You can solve your problem by reconsidering your design.
The short answer is no.
The closest you could get to this is using generics, however that would not work for a void, sorry.
public T Start()
One function name + combination of parameters can only be declared once, thus can only have one output.

Read-only ("const"-like) function parameters of C#

Coming from a C++ background, I'm used to sticking the const keyword into function definitions to make objects being passed in read-only values. However, I've found out that this is not possible in C# (please correct me if I'm wrong). After some Googling, I arrived at the conclusion that the only way to make a read-only object is to write an interface that only has 'get' properties and pass that in instead. Elegant, I must say.
public interface IFoo
{
IMyValInterface MyVal{ get; }
}
public class Foo : IFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
}
}
I would pass it into:
public void SomeFunction(IFoo fooVar)
{
// Cannot modify fooVar, Excellent!!
}
This is fine. However, in the rest of my code, I would like to modify my object normally. Adding a 'set' property to the interface would break my read-only restriction. I can add a 'set' property to Foo (and not IFoo), but the signature expects an interface rather than a concrete object. I would have to do some casting.
// Add this to class Foo. Might assign null if cast fails??
set { _myVal = value as ConcreteMyVal; }
// Somewhere else in the code...
IFoo myFoo = new Foo;
(myFoo as Foo).MyFoo = new ConcreteMyVal();
Is there a more elegant way of replicating const or making read-only function parameters without adding another property or a function?
I think you may be looking for a solution involving two interfaces in which one inherits from the other:
public interface IReadableFoo
{
IMyValInterface MyVal { get; }
}
public interface IWritableFoo : IReadableFoo
{
IMyValInterface MyVal { set; }
}
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
set { _myVal = value as ConcreteMyVal; }
}
}
Then you can declare methods whose parameter type “tells” whether it plans on changing the variable or not:
public void SomeFunction(IReadableFoo fooVar)
{
// Cannot modify fooVar, excellent!
}
public void SomeOtherFunction(IWritableFoo fooVar)
{
// Can modify fooVar, take care!
}
This mimics compile-time checks similar to constness in C++. As Eric Lippert correctly pointed out, this is not the same as immutability. But as a C++ programmer I think you know that.
By the way, you can achieve slightly better compile-time checking if you declare the type of the property in the class as ConcreteMyVal and implement the interface properties separately:
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public ConcreteMyVal MyVal
{
get { return _myVal; }
set { _myVal = value; }
}
public IMyValInterface IReadableFoo.MyVal { get { return MyVal; } }
public IMyValInterface IWritableFoo.MyVal
{
// (or use “(ConcreteMyVal)value” if you want it to throw
set { MyVal = value as ConcreteMyVal; }
}
}
This way, the setter can only throw when accessed through the interface, but not when accessed through the class.
The closest equivalent is the in keyword. Using in makes the parameter and input parameter and prevents it from being changed inside the method. From the official C# documentation:
in - specifies that this parameter is passed by reference but is only read by the called method.
ref - specifies that this parameter is passed by reference and may be read or written by the called method.
out - specifies that this parameter is passed by reference and must be written by the called method.
First of all, you're correct: you cannot apply const or a similar keyword to parameters in C#.
However, you can use interfaces to do something along those lines. Interfaces are special in the sense, that it makes perfect sense to make an interface that only covers a specific part of a feature set. E.g. image a stack class, which implements both IPopable and IPushable. If you access the instance via the IPopable interface, you can only remove entries from the stack. If you access the instance via the IPushable interface, you can only add entries to the stack. You can use interfaces this way to get something similar to what you're asking for.
Consider Timwi's answer first. But as a second option, you could do this, making it more like the C CONST keyword.
Reference-type (object) parameters are IN parameters by default. But because they are references, their method side effects and property accesses are done to the object outside the method. The object doesn't have to be passed out. It has still been modified by the method.
However, a value-type (struct) parameter is also IN by default, and cannot have side effects or property modifications on the element that was passed in. Instead, it gets COPIED ON WRITE before going into the method. Any changes to it inside that method die when the method goes out of scope (the end of the method).
Do NOT change your classes to structs just to accommodate this need. It's a bad idea. But if they should be structs anyway, now you'll know.
BTW, half the programming community doesn't properly understand this concept but thinks they do (indeed, I've found inaccuracies on the matter of parameter direction in C# in several books). If you want to comment on the accuracy of my statements, please double check to make sure you know what you're talking about.

C# virtual static method

Why is static virtual impossible? Is C# dependent or just don't have any sense in the OO world?
I know the concept has already been underlined but I did not find a simple answer to the previous question.
virtual means the method called will be chosen at run-time, depending on the dynamic type of the object. static means no object is necessary to call the method.
How do you propose to do both in the same method?
Eric Lippert has a blog post about this, and as usual with his posts, he covers the subject in great depth:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/calling-static-methods-on-type-parameters-is-illegal-part-one
“virtual” and “static” are opposites! “virtual” means “determine the method to be called based on run time type information”, and “static” means “determine the method to be called solely based on compile time static analysis”
The contradiction between "static" and "virtual" is only a C# problem. If "static" were replaced by "class level", like in many other languages, no one would be blindfolded.
Too bad the choice of words made C# crippled in this respect. It is still possible to call the Type.InvokeMember method to simulate a call to a class level, virtual method. You just have to pass the method name as a string. No compile time check, no strong typing and no control that subclasses implement the method.
Some Delphi beauty:
type
TFormClass = class of TForm;
var
formClass: TFormClass;
myForm: TForm;
begin
...
formClass = GetAnyFormClassYouWouldLike;
myForm = formClass.Create(nil);
myForm.Show;
end
Guys who say that there is no sense in static virtual methods - if you don't understand how this could be possible, it does not mean that it is impossible. There are languages that allow this!! Look at Delphi, for example.
I'm going to be the one who naysays. What you are describing is not technically part of the language. Sorry. But it is possible to simulate it within the language.
Let's consider what you're asking for - you want a collection of methods that aren't attached to any particular object that can all be easily callable and replaceable at run time or compile time.
To me that sounds like what you really want is a singleton object with delegated methods.
Let's put together an example:
public interface ICurrencyWriter {
string Write(int i);
string Write(float f);
}
public class DelegatedCurrencyWriter : ICurrencyWriter {
public DelegatedCurrencyWriter()
{
IntWriter = i => i.ToString();
FloatWriter = f => f.ToString();
}
public string Write(int i) { return IntWriter(i); }
public string Write(float f) { return FloatWriter(f); }
public Func<int, string> IntWriter { get; set; }
public Func<float, string> FloatWriter { get; set; }
}
public class SingletonCurrencyWriter {
public static DelegatedCurrencyWriter Writer {
get {
if (_writer == null)
_writer = new DelegatedCurrencyWriter();
return _writer;
}
}
}
in use:
Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400.0
SingletonCurrencyWriter.Writer.FloatWriter = f => String.Format("{0} bucks and {1} little pennies.", (int)f, (int)(f * 100));
Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400 bucks and 0 little pennies
Given all this, we now have a singleton class that writes out currency values and I can change the behavior of it. I've basically defined the behavior convention at compile time and can now change the behavior at either compile time (in the constructor) or run time, which is, I believe the effect you're trying to get. If you want inheritance of behavior, you can do that to by implementing back chaining (ie, have the new method call the previous one).
That said, I don't especially recommend the example code above. For one, it isn't thread safe and there really isn't a lot in place to keep life sane. Global dependence on this kind of structure means global instability. This is one of the many ways that changeable behavior was implemented in the dim dark days of C: structs of function pointers, and in this case a single global struct.
Yes it is possible.
The most wanted use case for that is to have factories which can be "overriden"
In order to do this, you will have to rely on generic type parameters using the F-bounded polymorphism.
Example 1
Let's take a factory example:
class A: { public static A Create(int number) { return ... ;} }
class B: A { /* How to override the static Create method to return B? */}
You also want createB to be accessible and returning B objects in the B class. Or you might like A's static functions to be a library that should be extensible by B. Solution:
class A<T> where T: A<T> { public static T Create(int number) { return ...; } }
class B: A<B> { /* no create function */ }
B theb = B.Create(2); // Perfectly fine.
A thea = A.Create(0); // Here as well
Example 2 (advanced):
Let's define a static function to multiply matrices of values.
public abstract class Value<T> where T : Value<T> {
//This method is static but by subclassing T we can use virtual methods.
public static Matrix<T> MultiplyMatrix(Matrix<T> m1, Matrix<T> m2) {
return // Code to multiply two matrices using add and multiply;
}
public abstract T multiply(T other);
public abstract T add(T other);
public abstract T opposed();
public T minus(T other) {
return this.add(other.opposed());
}
}
// Abstract override
public abstract class Number<T> : Value<T> where T: Number<T> {
protected double real;
/// Note: The use of MultiplyMatrix returns a Matrix of Number here.
public Matrix<T> timesVector(List<T> vector) {
return MultiplyMatrix(new Matrix<T>() {this as T}, new Matrix<T>(vector));
}
}
public class ComplexNumber : Number<ComplexNumber> {
protected double imag;
/// Note: The use of MultiplyMatrix returns a Matrix of ComplexNumber here.
}
Now you can also use the static MultiplyMatrix method to return a matrix of complex numbers directly from ComplexNumber
Matrix<ComplexNumber> result = ComplexNumber.MultiplyMatrix(matrix1, matrix2);
While technically it's not possible to define a static virtual method, for all the reasons already pointed out here, you can functionally accomplish what I think you're trying using C# extension methods.
From Microsoft Docs:
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.
Check out Extension Methods (C# Programming Guide) for more details.
In .NET, virtual method dispatch is (roughly) done by looking at the actual type of an object when the method is called at runtime, and finding the most overriding method from the class's vtable. When calling on a static class, there is no object instance to check, and so no vtable to do the lookup on.
To summarize all the options presented:
This is not a part of C# because in it, static means "not bound to anything at runtime" as it has ever since C (and maybe earlier). static entities are bound to the declaring type (thus are able to access its other static entities), but only at compile time.
This is possible in other languages where a static equivalent (if needed at all) means "bound to a type object at runtime" instead. Examples include Delphi, Python, PHP.
This can be emulated in a number of ways which can be classified as:
Use runtime binding
Static methods with a singleton object or lookalike
Virtual method that returns the same for all instances
Redefined in a derived type to return a different result (constant or derived from static members of the redefining type)
Retrieves the type object from the instance
Use compile-time binding
Use a template that modifies the code for each derived type to access the same-named entities of that type, e.g. with the CRTP
The 2022+ answer, if you are running .Net 7 or above, is that now static virtual members is now supported in interfaces. Technically it's static abstract instead of "static virtual" but the effect is that same. Standard static methods signatures can be defined in an interface and implemented statically.
Here are a few examples on the usage and syntax in .Net 7

Categories