1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
22
using NUnit.Framework;
23
using ICSharpCode.NRefactory.TypeSystem;
24
using ICSharpCode.NRefactory.Semantics;
26
namespace ICSharpCode.NRefactory.CSharp.Resolver
28
using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic;
32
public class ExplicitConversionsTest : ResolverTestBase
34
CSharpConversions conversions;
36
public override void SetUp()
39
conversions = new CSharpConversions(compilation);
42
Conversion ExplicitConversion(Type from, Type to)
44
IType from2 = compilation.FindType(from);
45
IType to2 = compilation.FindType(to);
46
return conversions.ExplicitConversion(from2, to2);
50
public void PointerConversion()
52
Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(int*), typeof(short)));
53
Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(short), typeof(void*)));
55
Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(void*), typeof(int*)));
56
Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(long*), typeof(byte*)));
60
public void ConversionFromDynamic()
62
// Explicit dynamic conversion is for resolve results only;
63
// otherwise it's an explicit reference / unboxing conversion
64
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(dynamic), typeof(string)));
65
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(dynamic), typeof(int)));
67
var dynamicRR = new ResolveResult(SpecialType.Dynamic);
68
Assert.AreEqual(C.ExplicitDynamicConversion, conversions.ExplicitConversion(dynamicRR, compilation.FindType(typeof(string))));
69
Assert.AreEqual(C.ExplicitDynamicConversion, conversions.ExplicitConversion(dynamicRR, compilation.FindType(typeof(int))));
73
public void NumericConversions()
75
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(sbyte), typeof(uint)));
76
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(sbyte), typeof(char)));
77
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(char)));
78
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(sbyte)));
79
// if an implicit conversion exists, ExplicitConversion() should return that
80
Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(byte), typeof(int)));
81
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(double), typeof(float)));
82
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(double), typeof(decimal)));
83
Assert.AreEqual(C.ExplicitNumericConversion, ExplicitConversion(typeof(decimal), typeof(double)));
84
Assert.AreEqual(C.ImplicitNumericConversion, ExplicitConversion(typeof(int), typeof(decimal)));
86
Assert.AreEqual(C.None, ExplicitConversion(typeof(bool), typeof(int)));
87
Assert.AreEqual(C.None, ExplicitConversion(typeof(int), typeof(bool)));
91
public void EnumerationConversions()
93
var explicitEnumerationConversion = C.EnumerationConversion(false, false);
94
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(sbyte), typeof(StringComparison)));
95
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(char), typeof(StringComparison)));
96
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(int), typeof(StringComparison)));
97
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(decimal), typeof(StringComparison)));
98
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(char)));
99
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(int)));
100
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(decimal)));
101
Assert.AreEqual(explicitEnumerationConversion, ExplicitConversion(typeof(StringComparison), typeof(StringSplitOptions)));
105
public void NullableConversion_BasedOnIdentityConversion()
107
Assert.AreEqual(C.IdentityConversion, ExplicitConversion(typeof(ArraySegment<dynamic>?), typeof(ArraySegment<object>?)));
108
Assert.AreEqual(C.ImplicitNullableConversion, ExplicitConversion(typeof(ArraySegment<dynamic>), typeof(ArraySegment<object>?)));
109
Assert.AreEqual(C.ExplicitNullableConversion, ExplicitConversion(typeof(ArraySegment<dynamic>?), typeof(ArraySegment<object>)));
113
public void NullableConversion_BasedOnImplicitNumericConversion()
115
Assert.AreEqual(C.ImplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(long?)));
116
Assert.AreEqual(C.ImplicitLiftedNumericConversion, ExplicitConversion(typeof(int), typeof(long?)));
117
Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(long)));
121
public void NullableConversion_BasedOnImplicitEnumerationConversion()
123
ResolveResult zero = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 0);
124
ResolveResult one = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1);
125
Assert.AreEqual(C.EnumerationConversion(true, true), conversions.ExplicitConversion(zero, compilation.FindType(typeof(StringComparison?))));
126
Assert.AreEqual(C.EnumerationConversion(false, true), conversions.ExplicitConversion(one, compilation.FindType(typeof(StringComparison?))));
130
public void NullableConversion_BasedOnExplicitNumericConversion()
132
Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(short?)));
133
Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int), typeof(short?)));
134
Assert.AreEqual(C.ExplicitLiftedNumericConversion, ExplicitConversion(typeof(int?), typeof(short)));
138
public void NullableConversion_BasedOnExplicitEnumerationConversion()
140
C c = C.EnumerationConversion(false, true); // c = explicit lifted enumeration conversion
141
Assert.AreEqual(c, ExplicitConversion(typeof(int?), typeof(StringComparison?)));
142
Assert.AreEqual(c, ExplicitConversion(typeof(int), typeof(StringComparison?)));
143
Assert.AreEqual(c, ExplicitConversion(typeof(int?), typeof(StringComparison)));
145
Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(int?)));
146
Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison), typeof(int?)));
147
Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(int)));
149
Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(StringSplitOptions?)));
150
Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison), typeof(StringSplitOptions?)));
151
Assert.AreEqual(c, ExplicitConversion(typeof(StringComparison?), typeof(StringSplitOptions)));
155
public void ExplicitReferenceConversion_SealedClass()
157
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object), typeof(string)));
158
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<char>), typeof(string)));
159
Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable<int>), typeof(string)));
160
Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable<object>), typeof(string)));
161
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(string), typeof(IEnumerable<char>)));
162
Assert.AreEqual(C.None, ExplicitConversion(typeof(string), typeof(IEnumerable<int>)));
163
Assert.AreEqual(C.None, ExplicitConversion(typeof(string), typeof(IEnumerable<object>)));
167
public void ExplicitReferenceConversion_NonSealedClass()
169
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object), typeof(List<string>)));
170
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<object>), typeof(List<string>)));
171
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<string>), typeof(List<string>)));
172
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<int>), typeof(List<string>)));
174
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(List<string>), typeof(IEnumerable<object>)));
175
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(List<string>), typeof(IEnumerable<string>)));
176
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(List<string>), typeof(IEnumerable<int>)));
178
Assert.AreEqual(C.None, ExplicitConversion(typeof(List<string>), typeof(List<object>)));
179
Assert.AreEqual(C.None, ExplicitConversion(typeof(List<string>), typeof(List<int>)));
183
public void ExplicitReferenceConversion_Interfaces()
185
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<string>), typeof(IEnumerable<object>)));
186
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<int>), typeof(IEnumerable<object>)));
187
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<object>), typeof(IEnumerable<string>)));
188
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<object>), typeof(IEnumerable<int>)));
189
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<object>), typeof(IConvertible)));
193
public void ExplicitReferenceConversion_Arrays()
195
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object[]), typeof(string[])));
196
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(dynamic[]), typeof(string[])));
197
Assert.AreEqual(C.None, ExplicitConversion(typeof(object[]), typeof(object[,])));
198
Assert.AreEqual(C.None, ExplicitConversion(typeof(object[]), typeof(int[])));
199
Assert.AreEqual(C.None, ExplicitConversion(typeof(short[]), typeof(int[])));
200
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Array), typeof(int[])));
204
public void ExplicitReferenceConversion_InterfaceToArray()
206
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(ICloneable), typeof(int[])));
207
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<string>), typeof(string[])));
208
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<object>), typeof(string[])));
209
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<string>), typeof(object[])));
210
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<string>), typeof(dynamic[])));
211
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(IEnumerable<int>), typeof(int[])));
212
Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable<string>), typeof(object[,])));
213
Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable<short>), typeof(object[])));
217
public void ExplicitReferenceConversion_ArrayToInterface()
219
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(int[]), typeof(ICloneable)));
220
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(string[]), typeof(IEnumerable<string>)));
221
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(string[]), typeof(IEnumerable<object>)));
222
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(object[]), typeof(IEnumerable<string>)));
223
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(dynamic[]), typeof(IEnumerable<string>)));
224
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(int[]), typeof(IEnumerable<int>)));
225
Assert.AreEqual(C.None, ExplicitConversion(typeof(object[,]), typeof(IEnumerable<string>)));
226
Assert.AreEqual(C.None, ExplicitConversion(typeof(object[]), typeof(IEnumerable<short>)));
230
public void ExplicitReferenceConversion_Delegates()
232
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(MulticastDelegate), typeof(Action)));
233
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Delegate), typeof(Action)));
234
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(ICloneable), typeof(Action)));
235
Assert.AreEqual(C.None, ExplicitConversion(typeof(System.Threading.ThreadStart), typeof(Action)));
239
public void ExplicitReferenceConversion_GenericDelegates()
241
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(Action<object>), typeof(Action<string>)));
242
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Action<string>), typeof(Action<object>)));
244
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Func<object>), typeof(Func<string>)));
245
Assert.AreEqual(C.ImplicitReferenceConversion, ExplicitConversion(typeof(Func<string>), typeof(Func<object>)));
247
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Action<IFormattable>), typeof(Action<IConvertible>)));
248
Assert.AreEqual(C.None, ExplicitConversion(typeof(Action<IFormattable>), typeof(Action<int>)));
249
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Action<string>), typeof(Action<IEnumerable<int>>)));
251
Assert.AreEqual(C.ExplicitReferenceConversion, ExplicitConversion(typeof(Func<IFormattable>), typeof(Func<IConvertible>)));
252
Assert.AreEqual(C.None, ExplicitConversion(typeof(Func<IFormattable>), typeof(Func<int>)));
253
Assert.AreEqual(C.None, ExplicitConversion(typeof(Func<string>), typeof(Func<IEnumerable<int>>)));
254
Assert.AreEqual(C.None, ExplicitConversion(typeof(Func<string>), typeof(Func<IEnumerable<int>>)));
258
public void UnboxingConversion()
260
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(int)));
261
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(decimal)));
262
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(ValueType), typeof(int)));
263
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(IFormattable), typeof(int)));
264
Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable<object>), typeof(int)));
265
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(Enum), typeof(StringComparison)));
266
Assert.AreEqual(C.None, ExplicitConversion(typeof(Enum), typeof(int)));
270
public void LiftedUnboxingConversion()
272
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(int?)));
273
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(object), typeof(decimal?)));
274
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(ValueType), typeof(int?)));
275
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(IFormattable), typeof(int?)));
276
Assert.AreEqual(C.None, ExplicitConversion(typeof(IEnumerable<object>), typeof(int?)));
277
Assert.AreEqual(C.UnboxingConversion, ExplicitConversion(typeof(Enum), typeof(StringComparison?)));
278
Assert.AreEqual(C.None, ExplicitConversion(typeof(Enum), typeof(int?)));
280
Conversion ResolveCast(string program)
282
return Resolve<ConversionResolveResult>(program).Conversion;
286
public void ObjectToTypeParameter()
288
string program = @"using System;
290
public void M<T>(object o) {
294
Assert.AreEqual(C.UnboxingConversion, ResolveCast(program));
298
public void UnrelatedClassToTypeParameter()
300
string program = @"using System;
302
public void M<T>(string o) {
306
Assert.AreEqual(C.None, ResolveCast(program));
310
public void IntefaceToTypeParameter()
312
string program = @"using System;
314
public void M<T>(IDisposable o) {
318
Assert.AreEqual(C.UnboxingConversion, ResolveCast(program));
322
public void TypeParameterToInterface()
324
string program = @"using System;
326
public void M<T>(T t) {
327
IDisposable d = $(IDisposable)t$;
330
Assert.AreEqual(C.BoxingConversion, ResolveCast(program));
334
public void ValueTypeToTypeParameter()
336
string program = @"using System;
338
public void M<T>(ValueType o) where T : struct {
342
Assert.AreEqual(C.UnboxingConversion, ResolveCast(program));
346
public void InvalidTypeParameterConversion()
348
string program = @"using System;
350
public void M<T, U>(T t) {
354
Assert.AreEqual(C.None, ResolveCast(program));
358
public void TypeParameterConversion1()
360
string program = @"using System;
362
public void M<T, U>(T t) where T : U {
366
Assert.AreEqual(C.BoxingConversion, ResolveCast(program));
370
public void TypeParameterConversion1Array()
372
string program = @"using System;
374
public void M<T, U>(T[] t) where T : U {
378
Assert.AreEqual(C.None, ResolveCast(program));
382
public void TypeParameterConversion2()
384
string program = @"using System;
386
public void M<T, U>(T t) where U : T {
390
Assert.AreEqual(C.UnboxingConversion, ResolveCast(program));
394
public void TypeParameterConversion2Array()
396
string program = @"using System;
398
public void M<T, U>(T[] t) where U : T {
402
Assert.AreEqual(C.None, ResolveCast(program));
406
public void ImplicitTypeParameterConversionWithClassConstraint()
408
string program = @"using System;
410
public void M<T, U>(T t) where T : class where U : class, T {
414
Assert.AreEqual(C.ExplicitReferenceConversion, ResolveCast(program));
418
public void ImplicitTypeParameterArrayConversionWithClassConstraint()
420
string program = @"using System;
422
public void M<T, U>(T[] t) where T : class where U : class, T {
426
Assert.AreEqual(C.ExplicitReferenceConversion, ResolveCast(program));
430
public void ImplicitTypeParameterConversionWithClassConstraintOnlyOnT()
432
string program = @"using System;
434
public void M<T, U>(T t) where U : class, T {
438
Assert.AreEqual(C.ExplicitReferenceConversion, ResolveCast(program));
442
public void ImplicitTypeParameterArrayConversionWithClassConstraintOnlyOnT()
444
string program = @"using System;
446
public void M<T, U>(T[] t) where U : class, T {
450
Assert.AreEqual(C.ExplicitReferenceConversion, ResolveCast(program));
454
public void SimpleUserDefinedConversion()
456
var rr = Resolve<ConversionResolveResult>(@"
459
public static explicit operator C1(C2 c2) {
469
Assert.IsTrue(rr.Conversion.IsValid);
470
Assert.IsTrue(rr.Conversion.IsUserDefined);
471
Assert.AreEqual("op_Explicit", rr.Conversion.Method.Name);
475
public void ExplicitReferenceConversionFollowedByUserDefinedConversion()
477
var rr = Resolve<ConversionResolveResult>(@"
481
public static explicit operator T(S s) { return null; }
488
Assert.IsTrue(rr.Conversion.IsValid);
489
Assert.IsTrue(rr.Conversion.IsUserDefined);
490
Assert.AreEqual("B", rr.Input.Type.Name);
494
public void ImplicitUserDefinedConversionFollowedByExplicitNumericConversion()
496
var rr = Resolve<ConversionResolveResult>(@"
498
public static implicit operator float(T t) { return 0; }
505
Assert.IsTrue(rr.Conversion.IsValid);
506
Assert.IsTrue(rr.Conversion.IsUserDefined);
507
// even though the user-defined conversion is implicit, the combined conversion is explicit
508
Assert.IsTrue(rr.Conversion.IsExplicit);
512
public void BothDirectConversionAndBaseClassConversionAvailable()
514
var rr = Resolve<ConversionResolveResult>(@"
518
public static explicit operator T(S s) { return null; }
519
public static explicit operator T(B b) { return null; }
526
Assert.IsTrue(rr.Conversion.IsValid);
527
Assert.IsTrue(rr.Conversion.IsUserDefined);
528
Assert.AreEqual("b", rr.Conversion.Method.Parameters.Single().Name);
532
public void UserDefinedExplicitConversion_PicksExactSourceTypeIfPossible() {
533
string program = @"using System;
535
public static explicit operator Convertible(int i) {return new Convertible(); }
536
public static explicit operator Convertible(short s) {return new Convertible(); }
540
var a = $(Convertible)33$;
543
var rr = Resolve<ConversionResolveResult>(program);
544
Assert.IsTrue(rr.Conversion.IsValid);
545
Assert.IsTrue(rr.Conversion.IsUserDefined);
546
Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name);
550
public void UserDefinedExplicitConversion_PicksMostEncompassedSourceTypeIfPossible() {
551
string program = @"using System;
553
public static explicit operator Convertible(long l) {return new Convertible(); }
554
public static explicit operator Convertible(uint ui) {return new Convertible(); }
558
var a = $(Convertible)(ushort)33$;
561
var rr = Resolve<ConversionResolveResult>(program);
562
Assert.IsTrue(rr.Conversion.IsValid);
563
Assert.IsTrue(rr.Conversion.IsUserDefined);
564
Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name);
568
public void UserDefinedExplicitConversion_PicksMostEncompassingSourceType() {
569
string program = @"using System;
571
public static explicit operator Convertible(int i) {return new Convertible(); }
572
public static explicit operator Convertible(ushort us) {return new Convertible(); }
576
var a = $(Convertible)(long)33$;
579
var rr = Resolve<ConversionResolveResult>(program);
580
Assert.IsTrue(rr.Conversion.IsValid);
581
Assert.IsTrue(rr.Conversion.IsUserDefined);
582
Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name);
586
public void UserDefinedExplicitConversion_NoMostEncompassingSourceTypeIsInvalid() {
587
string program = @"using System;
589
public static explicit operator Convertible(uint i) {return new Convertible(); }
590
public static explicit operator Convertible(short us) {return new Convertible(); }
594
var a = $(Convertible)(long)33$;
597
var rr = Resolve<ConversionResolveResult>(program);
598
Assert.IsFalse(rr.Conversion.IsValid);
602
public void UserDefinedExplicitConversion_PicksExactTargetTypeIfPossible() {
603
string program = @"using System;
605
public static explicit operator int(Convertible i) {return 0; }
606
public static explicit operator short(Convertible s) {return 0; }
610
var a = $(int)new Convertible()$;
613
var rr = Resolve<ConversionResolveResult>(program);
614
Assert.IsTrue(rr.Conversion.IsValid);
615
Assert.IsTrue(rr.Conversion.IsUserDefined);
616
Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name);
620
public void UserDefinedExplicitConversion_PicksMostEncompassingTargetTypeIfPossible() {
621
string program = @"using System;
623
public static explicit operator int(Convertible i) {return 0; }
624
public static explicit operator ushort(Convertible us) {return 0; }
628
var a = $(ulong)new Convertible()$;
631
var rr = Resolve<ConversionResolveResult>(program);
632
Assert.IsTrue(rr.Conversion.IsValid);
633
Assert.IsTrue(rr.Conversion.IsUserDefined);
634
Assert.AreEqual("us", rr.Conversion.Method.Parameters[0].Name);
638
public void UserDefinedExplicitConversion_PicksMostEncompassedTargetType() {
639
string program = @"using System;
641
public static explicit operator long(Convertible l) { return 0; }
642
public static explicit operator uint(Convertible ui) { return 0; }
646
var a = $(ushort)new Convertible()$;
649
var rr = Resolve<ConversionResolveResult>(program);
650
Assert.IsTrue(rr.Conversion.IsValid);
651
Assert.IsTrue(rr.Conversion.IsUserDefined);
652
Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name);
656
public void UserDefinedExplicitConversion_NoMostEncompassedTargetTypeIsInvalid() {
657
string program = @"using System;
659
public static explicit operator ulong(Convertible l) { return 0; }
660
public static explicit operator int(Convertible ui) { return 0; }
664
var a = $(ushort)new Convertible()$;
667
var rr = Resolve<ConversionResolveResult>(program);
668
Assert.IsFalse(rr.Conversion.IsValid);
672
public void UserDefinedExplicitConversion_AmbiguousIsInvalid() {
673
string program = @"using System;
675
public static explicit operator Convertible2(Convertible1 c) {return 0; }
678
public static explicit operator Convertible2(Convertible1 c) {return 0; }
682
var a = $(Convertible2)new Convertible1()$;
685
var rr = Resolve<ConversionResolveResult>(program);
686
Assert.IsFalse(rr.Conversion.IsValid);
690
public void UserDefinedExplicitConversion_Lifted() {
691
string program = @"using System;
693
public static explicit operator Convertible(int i) {return new Convertible(); }
696
public void M(int? i) {
697
a = $(Convertible?)i$;
700
var rr = Resolve<ConversionResolveResult>(program);
701
Assert.IsTrue(rr.Conversion.IsValid);
702
Assert.IsTrue(rr.Conversion.IsUserDefined);
703
Assert.IsTrue(rr.Conversion.IsLifted);
707
public void UserDefinedExplicitConversionFollowedByImplicitNullableConversion() {
708
string program = @"using System;
710
public static explicit operator Convertible(int i) {return new Convertible(); }
713
public void M(int i) {
714
a = $(Convertible?)i$;
717
var rr = Resolve<ConversionResolveResult>(program);
718
Assert.IsTrue(rr.Conversion.IsValid);
719
Assert.IsTrue(rr.Conversion.IsUserDefined);
720
Assert.IsFalse(rr.Conversion.IsLifted);
724
public void UserDefinedExplicitConversion_ExplicitNullable_ThenUserDefined() {
725
string program = @"using System;
727
public static explicit operator Convertible(int i) {return new Convertible(); }
728
public static explicit operator Convertible?(int? ni) {return new Convertible(); }
731
public void M(int? i) {
732
a = $(Convertible)i$;
735
var rr = Resolve<ConversionResolveResult>(program);
736
Assert.IsTrue(rr.Conversion.IsValid);
737
Assert.IsTrue(rr.Conversion.IsUserDefined);
738
Assert.IsFalse(rr.Conversion.IsLifted);
739
Assert.AreEqual("i", rr.Conversion.Method.Parameters[0].Name);
743
public void UserDefinedExplicitConversion_DefinedNullableTakesPrecedenceOverLifted() {
744
string program = @"using System;
746
public static explicit operator Convertible(int i) {return new Convertible(); }
747
public static explicit operator Convertible?(int? ni) {return new Convertible(); }
751
a = $(Convertible?)(int?)33$;
754
var rr = Resolve<ConversionResolveResult>(program);
755
Assert.IsTrue(rr.Conversion.IsValid);
756
Assert.IsTrue(rr.Conversion.IsUserDefined);
757
Assert.IsFalse(rr.Conversion.IsLifted);
758
Assert.AreEqual("ni", rr.Conversion.Method.Parameters[0].Name);
762
public void UserDefinedExplicitConversion_UIntConstant() {
763
string program = @"using System;
765
public static explicit operator Convertible(long l) {return new Convertible(); }
766
public static explicit operator Convertible(uint ui) {return new Convertible(); }
770
var a = $(Convertible)33$;
773
var rr = Resolve<ConversionResolveResult>(program);
774
Assert.IsTrue(rr.Conversion.IsValid);
775
Assert.IsTrue(rr.Conversion.IsUserDefined);
776
Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name);
780
public void UserDefinedExplicitConversion_NullableUIntConstant() {
781
string program = @"using System;
783
public static explicit operator Convertible(long? l) {return new Convertible(); }
784
public static explicit operator Convertible(uint? ui) {return new Convertible(); }
788
Convertible a = $(Convertible)33$;
791
var rr = Resolve<ConversionResolveResult>(program);
792
Assert.IsTrue(rr.Conversion.IsValid);
793
Assert.IsTrue(rr.Conversion.IsUserDefined);
794
Assert.AreEqual("ui", rr.Conversion.Method.Parameters[0].Name);
798
public void UseDefinedExplicitConversion_Lifted() {
801
public static explicit operator Convertible(int i) { return new Convertible(); }
804
public void M(int? i) {
805
a = $(Convertible?)i$;
808
var rr = Resolve<ConversionResolveResult>(program);
809
Assert.IsTrue(rr.Conversion.IsValid);
810
Assert.IsTrue(rr.Conversion.IsUserDefined);
811
Assert.IsTrue(rr.Conversion.IsLifted);
812
Assert.IsTrue(rr.Input is LocalResolveResult);
816
public void UserDefinedExplicitConversion_Short_Or_NullableByte_Target()
818
string program = @"using System;
820
public static explicit operator short(Test s) { return 0; }
821
public static explicit operator byte?(Test b) { return 0; }
824
public static void Main(string[] args)
826
int? x = $(int?)new Test()$;
829
var rr = Resolve<ConversionResolveResult>(program);
830
Assert.IsTrue(rr.Conversion.IsValid);
831
Assert.IsTrue(rr.Conversion.IsUserDefined);
832
Assert.AreEqual("System.Int16", rr.Conversion.Method.ReturnType.FullName);
836
public void UserDefinedExplicitConversion_Byte_Or_NullableShort_Target()
838
string program = @"using System;
840
public static explicit operator byte(Test b) { return 0; }
841
public static explicit operator short?(Test s) { return 0; }
844
public static void Main(string[] args)
846
int? x = $(int?)new Test()$;
849
var rr = Resolve<ConversionResolveResult>(program);
850
Assert.IsTrue(rr.Conversion.IsValid);
851
Assert.IsTrue(rr.Conversion.IsUserDefined);
852
Assert.AreEqual("s", rr.Conversion.Method.Parameters[0].Name);
856
public void ExplicitConversionOperatorsCanOverrideApplicableImplicitOnes()
860
public static explicit operator int(Convertible ci) {return 0; }
861
public static implicit operator short(Convertible cs) {return 0; }
865
int i = $(int)new Convertible()$; // csc uses the explicit conversion operator
868
var rr = Resolve<ConversionResolveResult>(program);
869
Assert.IsTrue(rr.Conversion.IsValid);
870
Assert.IsTrue(rr.Conversion.IsUserDefined);
871
Assert.AreEqual("ci", rr.Conversion.Method.Parameters[0].Name);
875
public void UserDefinedExplicitConversion_ConversionBeforeUserDefinedOperatorIsCorrect() {
876
string program = @"using System;
878
public static implicit operator Convertible(int l) {return new Convertible(); }
883
Convertible a = $(Convertible)i$;
886
var rr = Resolve<ConversionResolveResult>(program);
887
Assert.IsTrue(rr.Conversion.IsValid);
888
Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsValid);
889
Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsExplicit);
890
Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsNumericConversion);
891
Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsIdentityConversion);
895
public void UserDefinedExplicitConversion_ConversionAfterUserDefinedOperatorIsCorrect() {
896
string program = @"using System;
898
public static implicit operator long(Convertible i) {return 0; }
902
int a = $(int)new Convertible()$;
905
var rr = Resolve<ConversionResolveResult>(program);
906
Assert.IsTrue(rr.Conversion.IsValid);
907
Assert.IsTrue(rr.Conversion.ConversionBeforeUserDefinedOperator.IsIdentityConversion);
908
Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsValid);
909
Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsExplicit);
910
Assert.IsTrue(rr.Conversion.ConversionAfterUserDefinedOperator.IsNumericConversion);