Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 泛型-实现相互编译时类型安全的更干净的方法?_C#_Generics_Type Safety - Fatal编程技术网

C# 泛型-实现相互编译时类型安全的更干净的方法?

C# 泛型-实现相互编译时类型安全的更干净的方法?,c#,generics,type-safety,C#,Generics,Type Safety,假设您有一个由“父母”和“子女”组成的数据结构,其中父母和子女之间的引用是相互的: 从中借鉴,编写以下代码是为了保证父母和孩子之间的相互参照(不滥用反思): 虽然这样做很有效,但是Child在Child.Parent.set中被强制转换为TChild的点让我有点担心。虽然我不确定是否有方法使用这个抛出InvalidCastException的类,但它仍然不可能被打破 有没有更干净的方法来实现这种效果?首先,这个问题的答案对类似于您的父子关系通用建模体系结构有一些想法 第二,我强烈反对这种模式。它

假设您有一个由“父母”和“子女”组成的数据结构,其中父母和子女之间的引用是相互的:

从中借鉴,编写以下代码是为了保证父母和孩子之间的相互参照(不滥用反思):

虽然这样做很有效,但是
Child
Child.Parent.set
中被强制转换为
TChild
的点让我有点担心。虽然我不确定是否有方法使用这个抛出
InvalidCastException
的类,但它仍然不可能被打破


有没有更干净的方法来实现这种效果?

首先,这个问题的答案对类似于您的父子关系通用建模体系结构有一些想法

第二,我强烈反对这种模式。它令人困惑,可以说是对泛型的滥用,实际上它不是类型安全的。看

第三,您认为编译器可能错误地认为需要进行类型转换,并且不可能导致它失败,这种态度可能会在将来给您带来麻烦。我建议您在默认情况下,当编译器说您的程序不是类型安全的时,应该相信它是正确的,如果您认为编译器是错误的,则应该相信您可能没有仔细考虑:

class Car : Base<Car, Wheel>.Parent { ... }
class Wheel : Base<Car, Wheel>.Child { ... }
class AnotherWheel : Base<Car, Wheel>.Child { ... }
...
new Car() blah blah blah
new Wheel() blah blah blah
the wheel is the child of the car, blah blah blah
and what happens when you make a Car the parent of an AnotherWheel?
class-Car:Base.Parent{…}
类:Base.Child{…}
类另一个轮子:Base.Child{…}
...
新车等等
新车轮()诸如此类诸如此类
车轮是汽车的孩子,诸如此类
当你把一辆车变成另一个轮子的母车时会发生什么?
编译器说强制转换是必需的,这是完全正确的;我们不能断定转换是有效的,因为它不是

第四,如何解决这个问题而不滥用实际上不安全的泛型

有很多方法,但我想你不会喜欢的。例如:

  • 使底层对象不可变。孩子不认识父母;父母确实了解自己的孩子
  • 在底层不可变对象的顶部构造一个facade对象;孩子的外表确实知道他的父母
  • 当“编辑”立面时,通过构建树的新脊椎来构建新的底层不可变树
可以使用通用接口协方差构造这样一个系统,这样就不需要强制转换;这样做只是一种练习

作为一个预热练习,考虑如何构造一个通用的不可变的<代码> ISTACK < /代码>,这样当你把一只乌龟推到一堆老虎身上时,它就变成了一个不可改变的动物堆栈。


总的来说,我认为最好不要试图在C#type系统中捕捉这种限制

首先,这个问题的答案对类似于您的父子关系通用建模的体系结构有一些想法

第二,我强烈反对这种模式。它令人困惑,可以说是对泛型的滥用,实际上它不是类型安全的。看

第三,您认为编译器可能错误地认为需要进行类型转换,并且不可能导致它失败,这种态度可能会在将来给您带来麻烦。我建议您在默认情况下,当编译器说您的程序不是类型安全的时,应该相信它是正确的,如果您认为编译器是错误的,则应该相信您可能没有仔细考虑:

class Car : Base<Car, Wheel>.Parent { ... }
class Wheel : Base<Car, Wheel>.Child { ... }
class AnotherWheel : Base<Car, Wheel>.Child { ... }
...
new Car() blah blah blah
new Wheel() blah blah blah
the wheel is the child of the car, blah blah blah
and what happens when you make a Car the parent of an AnotherWheel?
class-Car:Base.Parent{…}
类:Base.Child{…}
类另一个轮子:Base.Child{…}
...
新车等等
新车轮()诸如此类诸如此类
车轮是汽车的孩子,诸如此类
当你把一辆车变成另一个轮子的母车时会发生什么?
编译器说强制转换是必需的,这是完全正确的;我们不能断定转换是有效的,因为它不是

第四,如何解决这个问题而不滥用实际上不安全的泛型

有很多方法,但我想你不会喜欢的。例如:

  • 使底层对象不可变。孩子不认识父母;父母确实了解自己的孩子
  • 在底层不可变对象的顶部构造一个facade对象;孩子的外表确实知道他的父母
  • 当“编辑”立面时,通过构建树的新脊椎来构建新的底层不可变树
可以使用通用接口协方差构造这样一个系统,这样就不需要强制转换;这样做只是一种练习

作为一个预热练习,考虑如何构造一个通用的不可变的<代码> ISTACK < /代码>,这样当你把一只乌龟推到一堆老虎身上时,它就变成了一个不可改变的动物堆栈。


总的来说,我认为最好不要试图在C#type系统中捕捉这种限制

天哪,请不要这样做。看看为什么这在C#中是一个糟糕的模式。@EricLippert-你确实会说,“在实践中,有时使用这种模式确实能以一种在C#中很难建模的方式务实地解决问题。”。我发现当我口述对象模型而其他人只是使用它时,这种方法很有用。这会减轻你看到的问题吗?天哪,请不要这样做。看看为什么这在C#中是一个糟糕的模式。@EricLippert-你确实会说,“在实践中,有时使用这种模式确实能以一种在C#中很难建模的方式务实地解决问题。”。我发现当我口述对象模型而其他人只是使用它时,这种方法很有用。这会缓解您看到的问题吗?您的示例听起来很像您的示例
class Car : Base<Car, Wheel>.Parent { ... }
class Wheel : Base<Car, Wheel>.Child { ... }
class AnotherWheel : Base<Car, Wheel>.Child { ... }
...
new Car() blah blah blah
new Wheel() blah blah blah
the wheel is the child of the car, blah blah blah
and what happens when you make a Car the parent of an AnotherWheel?