Pochylmy się nad następującym kodem
Łatwo odgadnąć, że zmienna x jest typu int, natomiast podczas przypisania wartości x do zmiennej y następuje niejawne rzutowanie do typu decimal. Jak robi to Roslyn? Napiszmy testowy kod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
const string sampleCode = @"using System; public class Foo { public void Y() { int x = 1; decimal y = x; } } "; var tree = SyntaxFactory.ParseSyntaxTree(sampleCode); var cSharpCompilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree }, references: new[] { MscorlibRef }); var semanticModel = cSharpCompilation.GetSemanticModel(tree); var declarations = tree.GetRoot().DescendantNodes() .OfType<LocalDeclarationStatementSyntax>() .ToArray(); Debug.Assert(declarations != null && declarations.Length == 2); foreach (var localDeclarationStatementSyntax in declarations) { var declaration = localDeclarationStatementSyntax.Declaration; foreach (var variableDeclaratorSyntax in declaration.Variables) { var initializer = variableDeclaratorSyntax.Initializer; if (initializer==null) continue; var initializerValue = initializer.Value; var initializerValueType = semanticModel.GetTypeInfo(initializerValue); Console.WriteLine("{0} {1} {2}", variableDeclaratorSyntax, initializerValueType.Type, initializerValueType.ConvertedType); } } |
Na konsoli otrzymamy wynik:
|
x = 1 int int y = x int decimal |
Co jednak gdybyśmy chcieli dowiedzieć się czegoś więcej o rzutowaniu typów. Rozważmy kod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
using System; public class XNumber { public XNumber(int x) { _x = x; } int _x; public static implicit operator int(XNumber src) { return src._x; } } public class Foo { public void Y() { XNumber x = new XNumber(1); decimal y = x; int z = x; } } |
[…]