C# 将not nullable转换为nullable属性后重新编译
我有一个项目,在C# 将not nullable转换为nullable属性后重新编译,c#,C#,我有一个项目,在MyRequest课程中涉及以下部分 public int TestName {get; set;} 它被另一个项目使用-我们称之为Foolike var request = new MyRequest { TestName = mainCustomerNumber, }; 过了一会儿,我将TestName更改为可为null的类型,即public int?TestName{get;set
MyRequest
课程中涉及以下部分
public int TestName {get; set;}
它被另一个项目使用-我们称之为Foo
like
var request = new MyRequest
{
TestName = mainCustomerNumber,
};
过了一会儿,我将TestName
更改为可为null的类型,即public int?TestName{get;set;}
并编译了涉及MyRequest
类的项目。我是否也需要重新编译projectFoo
?
你能告诉我们原因吗?你有两个项目。
“一”具有MyRequest类
“另一个”有Foo
并更改MyRequest类中TestName的类型
我想这是你的问题
如果您直接从Foo访问MyReueset,我认为不需要重新编译。
int
和int?
是两种完全不同的值类型。一个是System.Int32
,另一个是System.Nullable
。在源代码中只有一个?
的差异,这一事实只会掩盖这种差异
请注意,如果在引用类型(C#8.0)(如string?
)上使用了null/non-null选项,则可能不需要重新编译,因为这只是一个建议(编译器只需在string
类型上添加装饰属性)
请参见右侧窗格中的
在低级别(IL语言),int
和int?
的处理方式非常不同
这:
翻译为:
.field public valuetype [System.Private.CoreLib]System.Nullable`1<int32> Int1
.field public int32 Int2
// Methods
.method public hidebysig
instance void SetInt1 () cil managed
{
// Method begins at RVA 0x2050
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: newobj instance void valuetype [System.Private.CoreLib]System.Nullable`1<int32>::.ctor(!0)
IL_0007: stfld valuetype [System.Private.CoreLib]System.Nullable`1<int32> C::Int1
IL_000c: ret
} // end of method C::SetInt1
.method public hidebysig
instance void SetInt2 () cil managed
{
// Method begins at RVA 0x205e
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld int32 C::Int2
IL_0007: ret
} // end of method C::SetInt2
我实际上是在模拟它。为了憎恨
Foo
的人,让我们把这个类命名为Runner
,它将一个库引用为.dll,其名称是Test
。
Test
类只涉及publictinttestname{get;set;}
让我们扩展一下
//public int TestName {get; set;} equals to roughly
private int TestName ;
public void set_TestName(int value)
{
TestName = value;
}
public int get_TestName()
{
TestName = value;
}
当我想编译Runner
类时,它被转换为
Test x = new Test();
x.set_TestName(5);
Console.WriteLine(x.get_TestName());
Console.ReadKey();
现在,让我们将Test
类中的getter setter更改为public int?TestName{get;set;}
并展开它
//public int? TestName {get; set;} equals to roughly
private int? TestName ;
public void set_TestName(int? value)
{
TestName = value;
}
public int? get_TestName()
{
TestName = value;
}
并编译Test
类。但不是Runner
类。Runner
类生成以下消息
Unhandled Exception: System.MissingMethodException:
Method not found: 'Void NameSpaceOfTest.Test.set_TestName(Int32)'. <-----
at NameSpaceOfRunner.Runner.Main(String[] args)
未处理的异常:System.MissingMethodException:
找不到方法:“Void NameSpaceOfTest.Test.set_TestName(Int32)”。是的,你知道。你改变了合同。@MJ Wills你能详细说明你的答案吗?但是仍然有一个整数值被分配给了。不是真的。你改变了合同。所以,它需要重新编译。我是说,如果你愿意,你可以自己试试。编译MyRequest
,但不要编译Foo
,然后尝试运行该软件。看看会发生什么。@mjwills我也会犯同样的错误。我完全明白我需要它重新编译。但是为什么呢?@mjwills我想我已经找到了答案。->那个TestName=mainCustomerNumber
只是TestName=new Nullable(mainCustomerNumber)
在int?
案例中的语法糖。Foo中的代码看起来是一样的,但事实并非如此。@Heinzi根据IL代码判断,我会说是的。
//public int? TestName {get; set;} equals to roughly
private int? TestName ;
public void set_TestName(int? value)
{
TestName = value;
}
public int? get_TestName()
{
TestName = value;
}
Unhandled Exception: System.MissingMethodException:
Method not found: 'Void NameSpaceOfTest.Test.set_TestName(Int32)'. <-----
at NameSpaceOfRunner.Runner.Main(String[] args)