Esword
(James Esword)
November 6, 2015, 12:42pm
1
public static class Program
{
public int Main(int argc, AnsiChar** argv)
{
var a = new string[]{"a",null,"c"};
string log = "#1 ";
foreach(var item in a){
log += $"{item} ";
}
NSLog(log); // output: #1 a (null) c
printSeq(a);
}
public void printSeq<T>(ISequence<T> seq){
string log = "#2 ";
foreach(var item in seq){
log += $"{item} ";
}
NSLog(log); // output: #2 a c
}
}
And I’ve checked the code of ArrayUtils.idArrayToSequence
:
class method ArrayUtils.idArrayToSequence(val: array of id): INSFastEnumeration;
begin
for i: Integer := 0 to length(val) -1 do
yield val[i];
end;
It seems the cause is that yield
will skip null items. I’m not sure if it’s a bug or by design.
And this must be the cause of another bug I reported months ago:
Try this testcase:
public class SeqTest : Test{
public void EqualTest(){
Assert.AreEqual(new Sugar.Collections.List<string>(){"a",null,"b"}, new string[]{"a",null,"b"});
}
}
This case is passed on Android/Win, but failed on iOS:
EqualTest finished. State: Failed. Message: Element count differs. Expected: <2> but was: <3>
Do more test and you will find the cause is the null in array, and the iteration in AreEqual function dosen’t handle it properly.
Thanks, logged as bugs://73593
bugs://73593 got closed with status notfixable.
mh
(marc hoffman)
January 28, 2016, 5:30pm
4
I’m afraid this is not fixable, since Cocoa’s INSE numerable infrastructure does dot support nil
. (nil
means end of list).
Esword
(James Esword)
January 29, 2016, 6:42am
5
I have a solution: make a ArraySequence to handle nill issue for C style array.
Here’s the code:
public static class TestClass {
public static void test() {
var array = new string[] {"a", null, "b", null, "c", null, "d", null, "e", null};
// iterateSeq(array);
iterateSeq(idArrayToSequence(array));
}
public static void iterateSeq<T>(ISequence<T> seq) {
foreach (var item in seq) {
NSLog($"item: {item}");
}
}
public static INSFastEnumeration<T> idArrayToSequence<T>(T[] array) {
return new ArraySequence<T>(array);
}
}
public class ArraySequence<T> : INSFastEnumeration<T> {
private readonly T[] mArray;
public ArraySequence(T[] array) {
mArray = array;
}
public NSUInteger countByEnumeratingWithState(NSFastEnumerationState* state) objects(T* buffer) count(NSUInteger bufferLen) {
// 1) check
if (state->state == 0) {
state->state = 1;
state->mutationsPtr = (NativeUInt*)(&mArray);
}
// 2) return
var array = mArray;
var arrayLen = array.length;
var arrayIndex = state->state - 1;
var bufferIndex = 0;
while (arrayIndex < arrayLen && bufferIndex < bufferLen) {
buffer[bufferIndex++] = array[arrayIndex++];
}
state->itemsPtr = (id*)buffer;
state->state = arrayIndex + 1;
return bufferIndex;
}
}
Esword
(James Esword)
February 6, 2016, 2:24am
6
Has anyone investigated my solution as above?
bugs://73593 got reopened.
Esword
(James Esword)
February 22, 2016, 7:57am
8
Still no feedback…It’s simple to just replace your ArrayUtils.idArrayToSequence
with my idArrayToSequence
and check if it can pass all unit tests.
ck
(Carlo Kok)
February 22, 2016, 9:04am
9
But it’s not that simple, we need to make sure iterators work with null somehow, and this requires more than a simple patch of idArrayToSequence.
darkov
February 22, 2016, 9:18am
10
Isn’t the existing behaviour correct, which as I understand it, skips null values?
If we consider null to mean “no value” then why should they be returned?
Esword
(James Esword)
February 22, 2016, 10:34am
12
Is that means the yield implementation for Cocoa should be fixed instead of a specific patch for array? I can’t agree more actually. But if that thing is not fixable (I’m not sure), we can only patch it.
Esword
(James Esword)
February 22, 2016, 10:35am
13
It’s true for NSArray but here is common array which certainly supports null values. So a conversion from array to ISequence should not break this.
And for cross platform purpose, we should have a collection library supporting null values as Sugar does.
ck
(Carlo Kok)
February 22, 2016, 10:48am
14
Which is why I didn’t replace the code with what you wrote here but instead will spend some time thinking on how to best solve this.