Skip to content

Commit 81c8e60

Browse files
Merge branch 'issue/861' into use-csharp-10
2 parents 70d1413 + 15fda14 commit 81c8e60

4 files changed

Lines changed: 60 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1111
### VB -> C#
1212

1313
* Xml Namespace Imports now converted [#836](https://github.com/icsharpcode/CodeConverter/issues/836)
14+
* Use explicit cast when integral numeric types are casted to enum [#861](https://github.com/icsharpcode/CodeConverter/issues/861)
1415
* Correct inconsistent casing of event handlers [#854](https://github.com/icsharpcode/CodeConverter/issues/854)
1516

1617
### C# -> VB

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ public override async Task<CSharpSyntaxNode> VisitCTypeExpression(VBasic.Syntax.
284284
{
285285
var nodeForType = node;
286286
var convertMethodForKeyword = GetConvertMethodForKeywordOrNull(nodeForType);
287-
if (_semanticModel.GetTypeInfo(nodeForType).Type is INamedTypeSymbol typeSymbol && typeSymbol.IsEnumType()) {
287+
if (_semanticModel.GetTypeInfo(nodeForType).Type is INamedTypeSymbol typeSymbol && typeSymbol.IsEnumType() &&
288+
_semanticModel.GetTypeInfo(node.Expression).Type is {} expressionType && !expressionType.IsIntegralType() && !expressionType.IsEnumType()) {
288289
convertMethodForKeyword = GetConvertMethodForKeywordOrNull(typeSymbol.EnumUnderlyingType);
289290
} else if (convertMethodForKeyword != null) {
290291
nodeForType = null;

CodeConverter/Util/FromRoslyn/ITypeSymbolExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ public static bool IsUnexpressibleTypeParameterConstraint(this ITypeSymbol typeS
254254
return false;
255255
}
256256

257+
public static bool IsIntegralType(this ITypeSymbol? type) => type.IsNumericType() && !type.IsFractionalNumericType();
258+
257259
public static bool IsFractionalNumericType(this ITypeSymbol? type)
258260
{
259261
if (type != null) {

Tests/CSharp/TypeCastTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,61 @@ private void Test()
256256
}");
257257
}
258258

259+
[Fact]
260+
public async Task CastingIntegralTypeToEnumShouldUseExplicitCastAsync()
261+
{
262+
await TestConversionVisualBasicToCSharpAsync(
263+
@"
264+
Enum TestEnum
265+
None = 0
266+
End Enum
267+
Enum TestEnum2
268+
None = 1
269+
End Enum
270+
Class Class1
271+
Private Sub Test()
272+
Dim res = CType(5S, TestEnum)
273+
res = CType(5D, TestEnum)
274+
res = CType(5L, TestEnum)
275+
res = CType(5.4F, TestEnum)
276+
res = CType(5.7R, TestEnum)
277+
res = CType(5UL, TestEnum)
278+
res = CType(5, TestEnum)
279+
280+
Dim otherEnum = TestEnum2.None
281+
res = CType(otherEnum, TestEnum)
282+
End Sub
283+
End Class",
284+
@"using Microsoft.VisualBasic.CompilerServices; // Install-Package Microsoft.VisualBasic
285+
286+
internal enum TestEnum
287+
{
288+
None = 0
289+
}
290+
291+
internal enum TestEnum2
292+
{
293+
None = 1
294+
}
295+
296+
internal partial class Class1
297+
{
298+
private void Test()
299+
{
300+
TestEnum res = (TestEnum)5;
301+
res = (TestEnum)Conversions.ToInteger(5m);
302+
res = (TestEnum)5L;
303+
res = (TestEnum)Conversions.ToInteger(5.4f);
304+
res = (TestEnum)Conversions.ToInteger(5.7d);
305+
res = (TestEnum)5UL;
306+
res = (TestEnum)5;
307+
var otherEnum = TestEnum2.None;
308+
res = (TestEnum)otherEnum;
309+
}
310+
}
311+
");
312+
}
313+
259314
[Fact]
260315
public async Task TryCastObjectToGenericListAsync()
261316
{

0 commit comments

Comments
 (0)