C# 定义 class 实例永远不能为空(它只包含不包含数据)
C# define that a class instance can never be null (it only contains no data)
出于好奇:有没有办法创建一个 class,其对 class 实例的引用永远不会设置为 null?
就像只有一个只读指针,只能由 class 本身设置为 null。
我的想法是:
我希望有一个易于阅读/使用的对象,它要么与数据一起存在,要么不与数据一起存在(由 hasData = false 之类的属性显示)。它始终是可访问的,永远不应该为 null / 指向任何地方,作为副作用,它也消除了对象的 NullReferenceExceptions,这些对象有时应该没有值而不需要检查 null。
在这种情况下,您可能希望使用结构而不是 class。 Class 是引用类型,因此它的默认值为空,因此包含实例的变量可以为空(分配为空)。没有办法阻止它。另一方面,struct 是一个值类型,struct 的默认值是一个空结构 - 即一个结构,其成员设置为默认值(0 表示 int 字段,null 表示引用类型的字段等)
结构示例
public struct Foo
{
public int Bar;
}
及其用法(注意它没有实例化但仍然不是空的)
Foo foo;
foo.Bar = 1;
可以在 MSDN sites 上找到有关结构的更多信息。
此功能(目前)不存在。 Roslyn 论坛上有很多关于不可空引用类型的讨论:non-nullable reference types (the one billion $ mistake)。但是目前你不能限制引用类型变量分配null
值。
您可以改用值类型(结构),但它不存储在堆中,按值传递等
所有其他选项不能保证有人不会将 null
分配给您的引用类型的变量。但是您仍然可以使用 Null Object 模式之类的东西来简化您的生活(以与普通对象相同的方式处理没有数据的对象)。
正如 Anton 所提到的,您可以使用不能具有默认值 null 的结构。但我想你想要更像这样的东西:
public class DataObject
{
public static bool HasData
{
get
{
return myObject != null;
}
}
public static DataObject PresistentDataObject
{
get
{
return myObject;
}
}
static DataObject myObject = new DataObject();
}
这段代码似乎是不好的做法。也许你想求助于单例依赖注入之类的东西,这样可以避免像这样设置状态class。
如果您的 class 被命名为 foo,那么您将至少有一个构造函数(可能更多)。在该构造函数中,您会将变量分配给 false。
public foo(){
hasData = false;
}
正如@Anton 指出的那样,这仅在实例化变量时有效。
foo f = new foo();
如果您将其指定为 null,它仍将是 null:
foo f = null;
I'm not sure, I understand the question correctly or not. Let me add
some points here:
希望你误解了术语Instance
,如果你创建了class的实例那么它就不会是null
,让myClass
成为class 你已经创建了。您没有使用 myClass myClassObject
创建 class 的任何实例。只有当class的实例分配给它时,myClassObject
才会成为class的实例,直到那时它是null
,这意味着不存在。
通常,此类问题背后的动机会驱动 qualities/properties 解决方案。
我想,这里的动机是避免(错误的)代码的运行时异常,这些代码试图访问空引用,就好像它持有一个实例一样。
class Foo<T> {
T data; // might be null or hold an instance...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays(); // might return null...
}
bool DoSomething() {
return data.Value > 5; // might throw an exception...
}
// ... more members...
}
要防止此类错误,您可以借鉴 C# 的近亲语言 F#。
如果函数 T GetInstanceOfTInMysteriousWays<T>()
通过设计和约定被允许 return 一个实例或一个空值,那么该函数的更好设计是让它 return 而不是 T 而 Option<T>
。那么,Foo.data
的类型就不是T
而是Option<T>
,DoSomething()
中的用户代码不能简单地访问成员data.Value
。因此,这种常见的错误模式将被消除。
// Improved code from above
class Foo<T> {
Option<T> data; // Option is a struct type and cannot be null...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays();
}
bool DoSomething() {
if (data.IsSome() ) {
return data.TryGetValue().Value > 5;
}
return false;
}
}
现在唯一的问题是,在 C# 中哪里可以找到该选项类型?有几个 github 项目创建了这样的类型(google 是你的朋友)。您还可以考虑 link F# 核心库并使用那里定义的 Option 类型,也许还有一个小助手,如 this gist snippet.
中所示
正如其他人所提到的,您需要一个 struct
。
不过,我们可以换个角度(class)来解决这个问题:
既然变量可以指向null,那么让我们定义一个不能为null的变量:
private Class1 _c = new Class1();
public Class1 c { get { return _c; } set { if (value != null) _c = value; } }
因此 c
不会设置为 null
。
A struct
根据您的要求:
struct Struct1
{
public bool hasData { get { return Data != null; } }
public Class1 Data;
}
出于好奇:有没有办法创建一个 class,其对 class 实例的引用永远不会设置为 null? 就像只有一个只读指针,只能由 class 本身设置为 null。
我的想法是: 我希望有一个易于阅读/使用的对象,它要么与数据一起存在,要么不与数据一起存在(由 hasData = false 之类的属性显示)。它始终是可访问的,永远不应该为 null / 指向任何地方,作为副作用,它也消除了对象的 NullReferenceExceptions,这些对象有时应该没有值而不需要检查 null。
在这种情况下,您可能希望使用结构而不是 class。 Class 是引用类型,因此它的默认值为空,因此包含实例的变量可以为空(分配为空)。没有办法阻止它。另一方面,struct 是一个值类型,struct 的默认值是一个空结构 - 即一个结构,其成员设置为默认值(0 表示 int 字段,null 表示引用类型的字段等)
结构示例
public struct Foo
{
public int Bar;
}
及其用法(注意它没有实例化但仍然不是空的)
Foo foo;
foo.Bar = 1;
可以在 MSDN sites 上找到有关结构的更多信息。
此功能(目前)不存在。 Roslyn 论坛上有很多关于不可空引用类型的讨论:non-nullable reference types (the one billion $ mistake)。但是目前你不能限制引用类型变量分配null
值。
您可以改用值类型(结构),但它不存储在堆中,按值传递等
所有其他选项不能保证有人不会将 null
分配给您的引用类型的变量。但是您仍然可以使用 Null Object 模式之类的东西来简化您的生活(以与普通对象相同的方式处理没有数据的对象)。
正如 Anton 所提到的,您可以使用不能具有默认值 null 的结构。但我想你想要更像这样的东西:
public class DataObject
{
public static bool HasData
{
get
{
return myObject != null;
}
}
public static DataObject PresistentDataObject
{
get
{
return myObject;
}
}
static DataObject myObject = new DataObject();
}
这段代码似乎是不好的做法。也许你想求助于单例依赖注入之类的东西,这样可以避免像这样设置状态class。
如果您的 class 被命名为 foo,那么您将至少有一个构造函数(可能更多)。在该构造函数中,您会将变量分配给 false。
public foo(){
hasData = false;
}
正如@Anton 指出的那样,这仅在实例化变量时有效。 foo f = new foo();
如果您将其指定为 null,它仍将是 null: foo f = null;
I'm not sure, I understand the question correctly or not. Let me add some points here:
希望你误解了术语Instance
,如果你创建了class的实例那么它就不会是null
,让myClass
成为class 你已经创建了。您没有使用 myClass myClassObject
创建 class 的任何实例。只有当class的实例分配给它时,myClassObject
才会成为class的实例,直到那时它是null
,这意味着不存在。
通常,此类问题背后的动机会驱动 qualities/properties 解决方案。
我想,这里的动机是避免(错误的)代码的运行时异常,这些代码试图访问空引用,就好像它持有一个实例一样。
class Foo<T> {
T data; // might be null or hold an instance...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays(); // might return null...
}
bool DoSomething() {
return data.Value > 5; // might throw an exception...
}
// ... more members...
}
要防止此类错误,您可以借鉴 C# 的近亲语言 F#。
如果函数 T GetInstanceOfTInMysteriousWays<T>()
通过设计和约定被允许 return 一个实例或一个空值,那么该函数的更好设计是让它 return 而不是 T 而 Option<T>
。那么,Foo.data
的类型就不是T
而是Option<T>
,DoSomething()
中的用户代码不能简单地访问成员data.Value
。因此,这种常见的错误模式将被消除。
// Improved code from above
class Foo<T> {
Option<T> data; // Option is a struct type and cannot be null...
Foo<T>() {
data = GetInstanceOfTInMysteriousWays();
}
bool DoSomething() {
if (data.IsSome() ) {
return data.TryGetValue().Value > 5;
}
return false;
}
}
现在唯一的问题是,在 C# 中哪里可以找到该选项类型?有几个 github 项目创建了这样的类型(google 是你的朋友)。您还可以考虑 link F# 核心库并使用那里定义的 Option 类型,也许还有一个小助手,如 this gist snippet.
中所示正如其他人所提到的,您需要一个 struct
。
不过,我们可以换个角度(class)来解决这个问题:
既然变量可以指向null,那么让我们定义一个不能为null的变量:
private Class1 _c = new Class1();
public Class1 c { get { return _c; } set { if (value != null) _c = value; } }
因此 c
不会设置为 null
。
A struct
根据您的要求:
struct Struct1
{
public bool hasData { get { return Data != null; } }
public Class1 Data;
}