回答編集履歴

2

追記

2019/02/07 03:51

投稿

Zuishin
Zuishin

スコア28656

test CHANGED
@@ -691,3 +691,187 @@
691
691
  }
692
692
 
693
693
  ```
694
+
695
+
696
+
697
+ # 追記
698
+
699
+
700
+
701
+ 質問とは直接関係ありませんが、null を代入できる構造体の例。
702
+
703
+
704
+
705
+ ```C#
706
+
707
+ using System;
708
+
709
+ using System.Collections.Generic;
710
+
711
+
712
+
713
+ namespace ConsoleApp1
714
+
715
+ {
716
+
717
+ class Program
718
+
719
+ {
720
+
721
+ static void Main(string[] args)
722
+
723
+ {
724
+
725
+ MyNullable<int> a = null;
726
+
727
+ Console.WriteLine(a == null);
728
+
729
+ MyNullable<int> b = 1;
730
+
731
+ Console.WriteLine(b == null);
732
+
733
+ Console.WriteLine(b == 1);
734
+
735
+ Console.ReadKey();
736
+
737
+ // 結果は True, False, True になる。
738
+
739
+ }
740
+
741
+ }
742
+
743
+
744
+
745
+ struct MyNullable<T>
746
+
747
+ {
748
+
749
+ public MyNullable(T value)
750
+
751
+ {
752
+
753
+ HasValue = true;
754
+
755
+ Value = value;
756
+
757
+ }
758
+
759
+
760
+
761
+ public T Value { get; private set; }
762
+
763
+
764
+
765
+ public bool HasValue { get; private set; }
766
+
767
+
768
+
769
+ public override bool Equals(object obj)
770
+
771
+ {
772
+
773
+ switch (obj)
774
+
775
+ {
776
+
777
+ case null:
778
+
779
+ return !HasValue;
780
+
781
+ case T comparison:
782
+
783
+ return EqualityComparer<T>.Default.Equals(comparison, Value);
784
+
785
+ case MyNullable<T> comparison:
786
+
787
+ if (!comparison.HasValue && !HasValue) return true;
788
+
789
+ if (!comparison.HasValue || !HasValue) return false;
790
+
791
+ return EqualityComparer<T>.Default.Equals(comparison.Value, Value);
792
+
793
+ default:
794
+
795
+ return false;
796
+
797
+ }
798
+
799
+ }
800
+
801
+
802
+
803
+ public override int GetHashCode()
804
+
805
+ {
806
+
807
+ var hashCode = 1816676634;
808
+
809
+ hashCode = hashCode * -1521134295 + EqualityComparer<T>.Default.GetHashCode(Value);
810
+
811
+ hashCode = hashCode * -1521134295 + HasValue.GetHashCode();
812
+
813
+ return hashCode;
814
+
815
+ }
816
+
817
+
818
+
819
+ public static bool operator ==(MyNullable<T> nullable1, MyNullable<T> nullable2)
820
+
821
+ {
822
+
823
+ return Equals(nullable1, nullable2);
824
+
825
+ }
826
+
827
+
828
+
829
+ public static bool operator !=(MyNullable<T> nullable1, MyNullable<T> nullable2)
830
+
831
+ {
832
+
833
+ return !(nullable1 == nullable2);
834
+
835
+ }
836
+
837
+
838
+
839
+ public static implicit operator MyNullable<T>(Dummy dummy)
840
+
841
+ {
842
+
843
+ if (dummy != null) throw new InvalidCastException();
844
+
845
+ return default(MyNullable<T>);
846
+
847
+ }
848
+
849
+
850
+
851
+ public static implicit operator MyNullable<T>(T value)
852
+
853
+ {
854
+
855
+ return new MyNullable<T>(value);
856
+
857
+ }
858
+
859
+
860
+
861
+ public static explicit operator T(MyNullable<T> nullable)
862
+
863
+ {
864
+
865
+ return nullable.Value;
866
+
867
+ }
868
+
869
+ }
870
+
871
+
872
+
873
+ public class Dummy { }
874
+
875
+ }
876
+
877
+ ```

1

追記

2019/02/07 03:50

投稿

Zuishin
Zuishin

スコア28656

test CHANGED
@@ -5,3 +5,689 @@
5
5
 
6
6
 
7
7
  前の質問から結局何がしたいのかわかりませんが、手に余るなら LINQ はあきらめて素直に for を使うのがいいと思います。応用が利かないということは保守できないということです。
8
+
9
+
10
+
11
+ # 追記
12
+
13
+
14
+
15
+ LINQ を使うなら相性が悪いとわかっている二次元配列をわざわざ使わなくても別のものに変換すれば簡単になります。
16
+
17
+
18
+
19
+ ```C#
20
+
21
+ using System;
22
+
23
+ using System.Collections;
24
+
25
+ using System.Collections.Generic;
26
+
27
+ using System.Linq;
28
+
29
+
30
+
31
+ namespace ConsoleApp1
32
+
33
+ {
34
+
35
+ public static class Program
36
+
37
+ {
38
+
39
+ public static void Main(string[] args)
40
+
41
+ {
42
+
43
+ var cells = new int[,]
44
+
45
+ {
46
+
47
+ { 0, 0, 0 },
48
+
49
+ { 0, 0, 0 },
50
+
51
+ { 1, 1, 0 },
52
+
53
+ { 0, 0, 0 },
54
+
55
+ { 1, 1, 1 },
56
+
57
+ };
58
+
59
+ int index = cells
60
+
61
+ .Cast<int>()
62
+
63
+ .ToMap(new Xy(cells.GetLength(1), cells.GetLength(0)))
64
+
65
+ .GetRows()
66
+
67
+ .Select((a, i) => a.All(b => b == 0) ? new int?(i) : null)
68
+
69
+ .LastOrDefault(a => a != null)
70
+
71
+ ?? -1;
72
+
73
+ Console.WriteLine(index);
74
+
75
+ Console.ReadKey();
76
+
77
+ }
78
+
79
+ }
80
+
81
+
82
+
83
+ #region Xy
84
+
85
+ public static class XyExtension
86
+
87
+ {
88
+
89
+ public static Xy ToXy(this IEnumerable<int> source)
90
+
91
+ {
92
+
93
+ var list = source as IReadOnlyList<int> ?? source.ToList();
94
+
95
+ if (list.Count != 2) throw new ArgumentException();
96
+
97
+ return new Xy(list[0], list[1]);
98
+
99
+ }
100
+
101
+ }
102
+
103
+
104
+
105
+ public struct Xy : IReadOnlyList<int>
106
+
107
+ {
108
+
109
+ public Xy(int x, int y)
110
+
111
+ {
112
+
113
+ X = x;
114
+
115
+ Y = y;
116
+
117
+ hashCode = null;
118
+
119
+ area = null;
120
+
121
+ directions = null;
122
+
123
+ distance = null;
124
+
125
+ }
126
+
127
+
128
+
129
+ public int X { get; private set; }
130
+
131
+ public int Y { get; private set; }
132
+
133
+
134
+
135
+ public int Count { get { return 2; } }
136
+
137
+
138
+
139
+ public int this[int index]
140
+
141
+ {
142
+
143
+ get
144
+
145
+ {
146
+
147
+ switch (index)
148
+
149
+ {
150
+
151
+ case 0:
152
+
153
+ return X;
154
+
155
+ case 1:
156
+
157
+ return Y;
158
+
159
+ default:
160
+
161
+ throw new IndexOutOfRangeException();
162
+
163
+ }
164
+
165
+ }
166
+
167
+ }
168
+
169
+
170
+
171
+ public override bool Equals(object obj)
172
+
173
+ {
174
+
175
+ return base.Equals(obj);
176
+
177
+ }
178
+
179
+
180
+
181
+ private int? hashCode;
182
+
183
+ public override int GetHashCode()
184
+
185
+ {
186
+
187
+ if (hashCode == null)
188
+
189
+ {
190
+
191
+ hashCode = this.Aggregate(1861411795, (a, b) => a * -1521134295 + b);
192
+
193
+ }
194
+
195
+ return hashCode.Value;
196
+
197
+ }
198
+
199
+
200
+
201
+ public IEnumerator<int> GetEnumerator()
202
+
203
+ {
204
+
205
+ yield return X;
206
+
207
+ yield return Y;
208
+
209
+ }
210
+
211
+
212
+
213
+ IEnumerator IEnumerable.GetEnumerator()
214
+
215
+ {
216
+
217
+ return GetEnumerator();
218
+
219
+ }
220
+
221
+
222
+
223
+ public Xy Square()
224
+
225
+ {
226
+
227
+ return this * this;
228
+
229
+ }
230
+
231
+
232
+
233
+ public double Distance(Xy xy)
234
+
235
+ {
236
+
237
+ return (this - xy).Distance();
238
+
239
+ }
240
+
241
+
242
+
243
+ private double? distance;
244
+
245
+ public double Distance()
246
+
247
+ {
248
+
249
+ if (distance == null)
250
+
251
+ {
252
+
253
+ distance = Math.Sqrt(Square().Sum());
254
+
255
+ }
256
+
257
+ return distance.Value;
258
+
259
+ }
260
+
261
+
262
+
263
+ private int? area;
264
+
265
+ public int Area
266
+
267
+ {
268
+
269
+ get
270
+
271
+ {
272
+
273
+ if (area == null) area = X * Y;
274
+
275
+ return area.Value;
276
+
277
+ }
278
+
279
+ }
280
+
281
+
282
+
283
+ public override string ToString()
284
+
285
+ {
286
+
287
+ return string.Format("({0},{1})", X, Y);
288
+
289
+ }
290
+
291
+
292
+
293
+ private static List<Xy> directions;
294
+
295
+ private static IEnumerable<Xy> Spin(Xy source)
296
+
297
+ {
298
+
299
+ var item = source;
300
+
301
+ for (int i = 0; i < 4; i++)
302
+
303
+ {
304
+
305
+ yield return item;
306
+
307
+ item = new Xy(-item.Y, item.X);
308
+
309
+ }
310
+
311
+ }
312
+
313
+ public static IEnumerable<Xy> Directions
314
+
315
+ {
316
+
317
+ get
318
+
319
+ {
320
+
321
+ if (directions == null)
322
+
323
+ {
324
+
325
+ directions = Spin(new Xy(1, 0))
326
+
327
+ .Concat(Spin(new Xy(1, 1)))
328
+
329
+ .ToList();
330
+
331
+ }
332
+
333
+ return directions;
334
+
335
+ }
336
+
337
+ }
338
+
339
+
340
+
341
+ public static implicit operator Xy(int i)
342
+
343
+ {
344
+
345
+ return new Xy(i, i);
346
+
347
+ }
348
+
349
+
350
+
351
+ public static bool operator ==(Xy xy1, Xy xy2)
352
+
353
+ {
354
+
355
+ return EqualityComparer<Xy>.Default.Equals(xy1, xy2);
356
+
357
+ }
358
+
359
+
360
+
361
+ public static bool operator !=(Xy xy1, Xy xy2)
362
+
363
+ {
364
+
365
+ return !(xy1 == xy2);
366
+
367
+ }
368
+
369
+
370
+
371
+ public static Xy operator +(Xy xy1, Xy xy2)
372
+
373
+ {
374
+
375
+ return new Xy(xy1.X + xy2.X, xy1.Y + xy2.Y);
376
+
377
+ }
378
+
379
+
380
+
381
+ public static Xy operator -(Xy xy1, Xy xy2)
382
+
383
+ {
384
+
385
+ return new Xy(xy1.X - xy2.X, xy1.Y - xy2.Y);
386
+
387
+ }
388
+
389
+
390
+
391
+ public static Xy operator *(Xy xy1, Xy xy2)
392
+
393
+ {
394
+
395
+ return new Xy(xy1.X * xy2.X, xy1.Y * xy2.Y);
396
+
397
+ }
398
+
399
+
400
+
401
+ public static Xy operator /(Xy xy1, Xy xy2)
402
+
403
+ {
404
+
405
+ return new Xy(xy1.X / xy2.X, xy1.Y / xy2.Y);
406
+
407
+ }
408
+
409
+
410
+
411
+ public static Xy operator %(Xy xy1, Xy xy2)
412
+
413
+ {
414
+
415
+ return new Xy(xy1.X % xy2.X, xy1.Y % xy2.Y);
416
+
417
+ }
418
+
419
+ }
420
+
421
+ #endregion
422
+
423
+
424
+
425
+ #region Map
426
+
427
+ public static class MapExtension
428
+
429
+ {
430
+
431
+ public static Map<T> ToMap<T>(this IEnumerable<T> source, Xy size)
432
+
433
+ {
434
+
435
+ return new Map<T>(source, size);
436
+
437
+ }
438
+
439
+ }
440
+
441
+ public class Map<T> : IReadOnlyList<T>
442
+
443
+ {
444
+
445
+ public Map(T[] source, Xy size)
446
+
447
+ {
448
+
449
+ if (source.Length != size.Area) throw new ArgumentException();
450
+
451
+ Source = new T[source.Length];
452
+
453
+ source.CopyTo(Source, 0);
454
+
455
+ Size = size;
456
+
457
+ }
458
+
459
+ public Map(IReadOnlyList<T> source, Xy size)
460
+
461
+ : this(source as T[] ?? (source == null ? new T[0] : source.ToArray()), size) { }
462
+
463
+ public Map(IEnumerable<T> source, Xy size)
464
+
465
+ : this(source as IReadOnlyList<T> ?? (source == null ? new T[0] : source.ToArray()), size) { }
466
+
467
+
468
+
469
+ protected T[] Source { get; private set; }
470
+
471
+ public Xy Size { get; private set; }
472
+
473
+
474
+
475
+ public int Count { get { return Source.Length; } }
476
+
477
+
478
+
479
+ public Xy GetIndices(int index)
480
+
481
+ {
482
+
483
+ if (!Includes(index)) throw new ArgumentOutOfRangeException();
484
+
485
+ return new Xy(index % Size.X, index / Size.X);
486
+
487
+ }
488
+
489
+ public int GetIndex(Xy indices)
490
+
491
+ {
492
+
493
+ if (!Includes(indices)) throw new ArgumentOutOfRangeException();
494
+
495
+ return indices.Y * Size.X + indices.X;
496
+
497
+ }
498
+
499
+
500
+
501
+ public bool Includes(Xy indices)
502
+
503
+ {
504
+
505
+ return indices.X >= 0
506
+
507
+ && indices.Y >= 0
508
+
509
+ && indices.X < Size.X
510
+
511
+ && indices.Y < Size.Y;
512
+
513
+ }
514
+
515
+ public bool Includes(int index)
516
+
517
+ {
518
+
519
+ return index >= 0 && index < Count;
520
+
521
+ }
522
+
523
+
524
+
525
+ public T this[int index]
526
+
527
+ {
528
+
529
+ get { return Source[index]; }
530
+
531
+ set
532
+
533
+ {
534
+
535
+ Source[index] = value;
536
+
537
+ hashCode = null;
538
+
539
+ }
540
+
541
+ }
542
+
543
+ public T this[Xy indices]
544
+
545
+ {
546
+
547
+ get { return this[GetIndex(indices)]; }
548
+
549
+ set { this[GetIndex(indices)] = value; }
550
+
551
+ }
552
+
553
+
554
+
555
+ public IEnumerable<IReadOnlyList<T>> GetRows()
556
+
557
+ {
558
+
559
+ for (int y = 0; y < Size.Y; y++)
560
+
561
+ {
562
+
563
+ var result = new T[Size.X];
564
+
565
+ Array.Copy(Source, Size.X * y, result, 0, Size.X);
566
+
567
+ yield return result;
568
+
569
+ }
570
+
571
+ }
572
+
573
+
574
+
575
+ public IEnumerable<IReadOnlyList<T>> GetColumns()
576
+
577
+ {
578
+
579
+ for (int x = 0; x < Size.X; x++)
580
+
581
+ {
582
+
583
+ var result = new T[Size.Y];
584
+
585
+ int index = x;
586
+
587
+ for (int y = 0; y < Size.Y; y++)
588
+
589
+ {
590
+
591
+ result[y] = Source[index];
592
+
593
+ index += Size.X;
594
+
595
+ }
596
+
597
+ yield return result;
598
+
599
+ }
600
+
601
+ }
602
+
603
+
604
+
605
+ public IEnumerator<T> GetEnumerator()
606
+
607
+ {
608
+
609
+ foreach (var item in Source) yield return item;
610
+
611
+ }
612
+
613
+
614
+
615
+ IEnumerator IEnumerable.GetEnumerator()
616
+
617
+ {
618
+
619
+ return GetEnumerator();
620
+
621
+ }
622
+
623
+
624
+
625
+ public override string ToString()
626
+
627
+ {
628
+
629
+ return string.Join("\n", GetRows().Select(a => string.Join(" ", a)));
630
+
631
+ }
632
+
633
+
634
+
635
+ public override bool Equals(object obj)
636
+
637
+ {
638
+
639
+ var d = obj as Map<T>;
640
+
641
+ return d != null && Source.SequenceEqual(d.Source) && Size == d.Size;
642
+
643
+ }
644
+
645
+
646
+
647
+ int? hashCode;
648
+
649
+ public override int GetHashCode()
650
+
651
+ {
652
+
653
+ if (hashCode == null)
654
+
655
+ {
656
+
657
+ hashCode = Source.Aggregate(262889186, (a, b) => a * -1521134295 + b.GetHashCode());
658
+
659
+ hashCode = hashCode * -1521134295 + Size.GetHashCode();
660
+
661
+ }
662
+
663
+ return hashCode.Value;
664
+
665
+ }
666
+
667
+
668
+
669
+ public static bool operator ==(Map<T> d1, Map<T> d2)
670
+
671
+ {
672
+
673
+ return EqualityComparer<Map<T>>.Default.Equals(d1, d2);
674
+
675
+ }
676
+
677
+
678
+
679
+ public static bool operator !=(Map<T> d1, Map<T> d2)
680
+
681
+ {
682
+
683
+ return !(d1 == d2);
684
+
685
+ }
686
+
687
+ }
688
+
689
+ #endregion
690
+
691
+ }
692
+
693
+ ```