Q1
struct A
{
int sum;
public int Sum(Action<int, int> log)
{
sum = 0;
for (var i = 0; i < 10; i++)
{
sum += i;
log(i, sum);
}
return sum;
}
}
上記のクラスのSum
メソッドは常に45
を返してきそうな感じがしますね。
実はSumメソッドに渡す引数次第では他の値が返ってくる可能性があります。
どのような引数を与えれば他の値を返すことができるでしょうか。
答え(リフレクションあり)
var temp = new[]{(object)(new A())};
var sumMethod = typeof(A).GetMethod("Sum");
var sumField = typeof(A).GetField("sum", BindingFlags.NonPublic | BindingFlags.Instance);
var result = sumMethod.Invoke(temp[0], new object[]
{
new Action<int, int>((i, sum) =>
{
sumField.SetValue(temp[0], 999);
Console.WriteLine($"i:{i} sum:{sum}");
}),
});
Console.WriteLine(result);
/*
i:0 sum:0
i:1 sum:1000
i:2 sum:1001
i:3 sum:1002
i:4 sum:1003
i:5 sum:1004
i:6 sum:1005
i:7 sum:1006
i:8 sum:1007
i:9 sum:1008
999
*/
答え(リフレクションなし)
var a = new A();
var result = a.Sum((i, sum) =>
{
a = new A();
Console.WriteLine($"i:{i} sum:{sum}");
});
Console.WriteLine(result);
/*
i:0 sum:0
i:1 sum:1
i:2 sum:2
i:3 sum:3
i:4 sum:4
i:5 sum:5
i:6 sum:6
i:7 sum:7
i:8 sum:8
i:9 sum:9
0
*/
Q2
interface ITest
{
}
struct A
{
int elemCount;
public int Init<T>(Span<T> s)
where T : ITest
{
elemCount = 0;
foreach (ref var i in s)
{
elemCount++;
i = default;
}
return elemCount;
}
}
似たような問題です。
Init
メソッドに要素数1以上のSpanを渡した場合、必ず1以上の値が返ってきそうな感じがします。
これも引数次第では1以上の値が返ってこない可能性があります。
どのような引数を与えればいいでしょうか。
答え
struct AA : ITest
{
public A a;
}
static void Do()
{
Span<AA> s = stackalloc AA[1];
var result = s[0].a.Init(s);
Console.WriteLine(result);
}
/*
0
*/
最後に
どちらの解答も思いついた方は相当C#に詳しい方だと思います。
こんなこと知ってなくてもC#を書くことはできますがもしかしたら役に立つときが来るかもしれません。