Roslyn c# 编译器:非托管结构被检测为可为空,但我想知道这是否是一个悖论
Roslyn c# compiler: unmanaged struct is detected as nullable, but I wonder if it's a paradox
突然之间,我在已经运行了很长时间的代码上遇到了一个我无法弄清楚的编译错误。这可通过 C# 7.3 重现。以下结构从未改变:
public interface ILocalInputEntityStruct<T> where T : unmanaged
{
//wouldn't the implementation of this interface prove
//that the struct doesn't have nullable fields (so it's unmanaged for c# 7.3)?
}
public struct LocalInputEntityStruct:ILocalInputEntityStruct<LocalInputEntityStruct>, IEntityComponent, INeedEGID
{
public float2 cameraAngles;
public float cameraZoomFactor;
public float roll;
public ActionInput actionMask;
public GuiInput guiMask;
}
而在下面的代码中,发现在与声明之一不同的程序集中,QueryEntity 期望 T 是非托管的,但编译器认为该结构是可为空的:
ref var localInput = ref entitiesDB.QueryEntity<LocalInputEntityStruct>(
playerId, InputExclusiveGroups.LocalPlayers);
编译此行导致错误
VisualCameraInputEngine.cs(60, 53): [CS8377] The type 'LocalInputEntityStruct' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'EntityDBExtensions.QueryEntity<T>(EntitiesDB, uint, ExclusiveGroupStruct)'
现在,我不能确定问题是否只是隐藏在之前,因为约束在新代码中的工作方式可能有所不同,但如果我对编译器工作方式的假设是正确的,那么这在我看来就像一个悖论。 VisualCameraInputEngine.cs 不应该编译之前 LocalInputEntityStruct 和 LocalInputEntityStruct 如果它可以为 null 就不能编译,对吧?该结构本身是 100% 非托管的,并且没有可为空的字段,但由于它是一个复杂的结构,实现具有非托管约束的接口是我证明这一点的方法。
编辑:QueryEntity 声明:
public static class EntityDBExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T QueryEntity<T>(this EntitiesDB entitiesDb, uint id, ExclusiveGroupStruct group) where T : unmanaged, IEntityComponent
{
throw new Exception("keeping this code simple for the purpose of the stack overflow question");
}
}
public static class EntityDBExtensionsB
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T QueryEntity<T>(this EntitiesDB entitiesDb, uint id, ExclusiveGroupStruct group) where T : struct, IEntityViewComponent
{
throw new Exception("keeping this code simple for the purpose of the stack overflow question");
}
}
注意:如果我不使用单独的程序集,可以编译相同的代码。
OS 信息:
Windows10, MSBuild 2017 (c# 7.3)
我在这里写信是因为我正在寻找可以解释为什么会发生这种情况的专家(对此我将非常感激)或者认为这可能是 Roslyn 错误(在这种情况下我将报告罗斯林 github).
我不排除我遗漏了一些关于程序集如何工作的东西,而且我不知道。
问题已被微软确认,解释如下:
突然之间,我在已经运行了很长时间的代码上遇到了一个我无法弄清楚的编译错误。这可通过 C# 7.3 重现。以下结构从未改变:
public interface ILocalInputEntityStruct<T> where T : unmanaged
{
//wouldn't the implementation of this interface prove
//that the struct doesn't have nullable fields (so it's unmanaged for c# 7.3)?
}
public struct LocalInputEntityStruct:ILocalInputEntityStruct<LocalInputEntityStruct>, IEntityComponent, INeedEGID
{
public float2 cameraAngles;
public float cameraZoomFactor;
public float roll;
public ActionInput actionMask;
public GuiInput guiMask;
}
而在下面的代码中,发现在与声明之一不同的程序集中,QueryEntity 期望 T 是非托管的,但编译器认为该结构是可为空的:
ref var localInput = ref entitiesDB.QueryEntity<LocalInputEntityStruct>(
playerId, InputExclusiveGroups.LocalPlayers);
编译此行导致错误
VisualCameraInputEngine.cs(60, 53): [CS8377] The type 'LocalInputEntityStruct' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'EntityDBExtensions.QueryEntity<T>(EntitiesDB, uint, ExclusiveGroupStruct)'
现在,我不能确定问题是否只是隐藏在之前,因为约束在新代码中的工作方式可能有所不同,但如果我对编译器工作方式的假设是正确的,那么这在我看来就像一个悖论。 VisualCameraInputEngine.cs 不应该编译之前 LocalInputEntityStruct 和 LocalInputEntityStruct 如果它可以为 null 就不能编译,对吧?该结构本身是 100% 非托管的,并且没有可为空的字段,但由于它是一个复杂的结构,实现具有非托管约束的接口是我证明这一点的方法。
编辑:QueryEntity 声明:
public static class EntityDBExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T QueryEntity<T>(this EntitiesDB entitiesDb, uint id, ExclusiveGroupStruct group) where T : unmanaged, IEntityComponent
{
throw new Exception("keeping this code simple for the purpose of the stack overflow question");
}
}
public static class EntityDBExtensionsB
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T QueryEntity<T>(this EntitiesDB entitiesDb, uint id, ExclusiveGroupStruct group) where T : struct, IEntityViewComponent
{
throw new Exception("keeping this code simple for the purpose of the stack overflow question");
}
}
注意:如果我不使用单独的程序集,可以编译相同的代码。
OS 信息:
Windows10, MSBuild 2017 (c# 7.3)
我在这里写信是因为我正在寻找可以解释为什么会发生这种情况的专家(对此我将非常感激)或者认为这可能是 Roslyn 错误(在这种情况下我将报告罗斯林 github).
我不排除我遗漏了一些关于程序集如何工作的东西,而且我不知道。
问题已被微软确认,解释如下: