|
| 1 | +using System; |
| 2 | +using Microsoft.VisualStudio.TestTools.UnitTesting; |
| 3 | + |
| 4 | +namespace Inasync.Tests { |
| 5 | + |
| 6 | + [TestClass] |
| 7 | + public class IssueTests { |
| 8 | + |
| 9 | + [TestMethod] |
| 10 | + public void Issue15_Test() => Issue15.Test(); |
| 11 | + |
| 12 | + private static class Issue15 { |
| 13 | + |
| 14 | + public static void Test() { |
| 15 | + IDerived x = new Derived { V0 = 0, V1 = 1 }; |
| 16 | + |
| 17 | + Action TestCase(int testNo, object y, Type? expectedException = null) => () => { |
| 18 | + TestAA |
| 19 | + .Act(() => x.AssertIs(y)) |
| 20 | + .Assert(expectedException, message: $"No.{testNo}"); |
| 21 | + }; |
| 22 | + |
| 23 | + new[] { |
| 24 | + TestCase( 0, y: new { V1 = 1 }, expectedException: typeof(PrimitiveAssertFailedException)), // y が IDerived のデータメンバーを全て実装していないので失敗すべき。 |
| 25 | + TestCase( 1, y: new { V0 = 0, V1 = 1 }), |
| 26 | + }.Invoke(); |
| 27 | + } |
| 28 | + |
| 29 | + private interface IBase { |
| 30 | + int V0 { get; } |
| 31 | + } |
| 32 | + |
| 33 | + private interface IDerived : IBase { |
| 34 | + int V1 { get; } |
| 35 | + } |
| 36 | + |
| 37 | + private class Derived : IDerived { |
| 38 | + public int V0 { get; set; } |
| 39 | + public int V1 { get; set; } |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + [TestMethod] |
| 44 | + public void Issue15_2_Test() => Issue15_2.Test(); |
| 45 | + |
| 46 | + private static class Issue15_2 { |
| 47 | + |
| 48 | + public static void Test() { |
| 49 | + var x = new FooBar(foo: 1, bar: 2, value: "foo bar", fooValue: "foo", barValue: "bar"); |
| 50 | + |
| 51 | + static Action TestCase<T>(int testNo, T x, object y, Type? expectedException = null) => () => { |
| 52 | + TestAA |
| 53 | + .Act(() => x.AssertIs(y)) |
| 54 | + .Assert(expectedException, message: $"No.{testNo}"); |
| 55 | + }; |
| 56 | + |
| 57 | + new[] { |
| 58 | + TestCase( 0, (FooBar)x , y: new { Foo = 1, Bar = 2, Value = "foo bar" }), |
| 59 | + TestCase( 1, (IFoo)x , y: new { Foo = 1, Value = "foo" }), |
| 60 | + TestCase( 2, (IBar)x , y: new { Bar = 2, Value = "bar" }), |
| 61 | + TestCase( 3, (IFooBar)x, y: new { Foo = 1, Bar = 2, Value = "foo bar" }, expectedException: typeof(ArgumentException)), // CS0229 相当: IFoo.Value と IBar.Value 間があいまい |
| 62 | + TestCase( 4, (IFooBar)x, y: new FooBar(foo: 1, bar: 2, value: "foo bar", fooValue: "foo", barValue: "bar"), expectedException: typeof(ArgumentException)), // 実体が等価に見えても、ターゲット型 IFooBar の Value があいまいなまま |
| 63 | + TestCase( 5, (IFooBar)x, y: x), // 参照等価であれば、IFooBar.Value のあいまいさを解決する必要が無いので、成功 |
| 64 | + }.Invoke(); |
| 65 | + } |
| 66 | + |
| 67 | + private interface IFoo { |
| 68 | + int Foo { get; } |
| 69 | + string Value { get; } |
| 70 | + } |
| 71 | + |
| 72 | + private interface IBar { |
| 73 | + int Bar { get; } |
| 74 | + string Value { get; } |
| 75 | + } |
| 76 | + |
| 77 | + private interface IFooBar : IFoo, IBar { } |
| 78 | + |
| 79 | + private sealed class FooBar : IFooBar { |
| 80 | + private readonly string _fooValue; |
| 81 | + private readonly string _barValue; |
| 82 | + |
| 83 | + public FooBar(int foo, int bar, string value, string fooValue, string barValue) { |
| 84 | + Foo = foo; |
| 85 | + Bar = bar; |
| 86 | + Value = value; |
| 87 | + _fooValue = fooValue; |
| 88 | + _barValue = barValue; |
| 89 | + } |
| 90 | + |
| 91 | + public int Foo { get; } |
| 92 | + public int Bar { get; } |
| 93 | + public string Value { get; } |
| 94 | + string IFoo.Value => _fooValue; |
| 95 | + string IBar.Value => _barValue; |
| 96 | + } |
| 97 | + } |
| 98 | + } |
| 99 | +} |
0 commit comments