+ 1
3 answers about C# syntax/compiler
1- if got a readonly field within an abstract base class, why cannot initialize it with ctor of derived class? (the abstract base class inherits an interface, just info ) 2- there's some way to pass arguments (for parametrized ctor) when creating an array of objects (initialization of the array, or some other assignation)? 3- why when iterate a list with foreach it throws error; im using the same type of the list elements as iterator (the type of the list is the of abstract base class, and the instances in that list are of the derived class) hope the explanations make sense (if need a code example tell me and I make it)
7 ответов
+ 4
Kiwwi# Sorry for not responding sooner. Busy busy day.
The issue with your code is you cannot remove an item from a collection while it's being enumerated.
Otherwise, the enumerator will be out of sync with the new state of the collection.
This is common in most languages I'm aware of.
----
That said, if removing an item during a loop iteration is absolutely necessary for some reason, use a for or while loop to iterate using an index instead of the enumerator.
The preferred way to remove would be in bulk based on a predicate expression that returns true for items that meet some criteria for being deleted.
The example below removes all posts with an "mfd" tag over the past 24 hours:
posts.ToList().RemoveAll(
post => post.Tags.Any(
tag => tag.Name.ToLower() == "mfd"));
+ 5
Kiwwi# I'm about to sleep, but I'll post some quick responses in case I hit the mark.
1. I'm guessing, the compiler requires the readonly field to be initialized in the containing class' constructor.
Otherwise, the compiler will need to either check every derived class constructor to validate every readonly field has been initialized throughout the entire class hierarchy structure. Or it would require all constructors to be responsible for initializing all readonly fields. That would be crazy.
So... it makes more sense to just enforce the initialization check in the containing class, which, in your case, is abstract.
...
+ 5
Kiwwi#
2. Use the base() keyword to pass arguments up the hierarchy chain within the constructor.
Example:
abstract class Rectangle {
protected readonly Color Color;
public Rectangle(Color color) {
Color = color;
}
}
class Square : Rectangle {
public Square (Color color)
: base(color) {}
}
You might need to double check syntax. I'm just posting quickly.
--------
3. I'd need to see what your code looks like for your third question.
+ 4
Kiwwi# A few good links to review on foreach are as follows:
https://blog.magnusmontin.net/2015/02/28/enumerating-collections-that-change-in-csharp/
https://kodify.net/csharp/loop/foreach-read-only/
https://kodify.net/csharp/loop/foreach-interface/
https://www.techiedelight.com/remove-elements-from-list-while-iterating-csharp/
+ 3
Kiwwi# I missed your earlier response regarding the line below:
----
Base [ ] arr = new Derived( arg )[10];
----
The problem with this line is you're trying to instantiate an instance of Derived( arg ) with syntax used for initializing an array size. The compiler has no idea what you're trying to do here.
I think what you want is something like the following:
----
var arr = new Base[10] {
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg ),
new Derived( arg )
};
----
This is actually initializing the Base arr variable with 10 instances of Derived.
Or you could instantiate once and assign 10 times:
----
var arr = Enumerable
.Repeat<Base>(new Derived(arg), 10)
.ToArray();
----
See my code in action.
https://code.sololearn.com/cT7Mwyyem5mz/?ref=app
+ 1
David Carroll thx for answer
I up a code example for point 3.
about the 2 question..
i refer to how put an argument to all the constructors of the array object elements while array initialization (or later)
example:
BaseClass [ ] arr = new DerivedClass( arg )[10];
// wich will not compile cause cannot put parentheses of ctor
**************************************
maybe: (but isn't in declaration)
Base [ ] arr = new Base[10];
for( int i = 0; i < arr.Lenght; i++ )
arr[ i ] = new Derived( arg );
// it overrides the old elements with the derived type, but maybe there's a better more direct way
some way of do definition in declaration?
+ 1
example point 3
https://code.sololearn.com/cLcybN4B8YeO/?ref=app