considere lo que sucede si nos desviamos de la convención CRTP escribiendo ...
public class Foo : TreeNode<Foo>
{
}
public class Bar : TreeNode<Foo> // parting from convention
{
}
... y luego llamar el código anterior de la siguiente manera:
var foo = new Foo();
var foobar = new Bar();
foobar.AddChild(foo);
La llamada AddChild
lanza una InvalidCastException
diciendo Unable to cast object of type 'Bar' to type 'Foo'.
En cuanto a la expresión idiomática CRTP, es solo una convención que requiere que el tipo genérico sea el mismo que el de declar tipo de ing. El lenguaje debe ser compatible con los otros casos donde no se sigue la convención de CRTP. Eric Lippert escribió una gran publicación de blog sobre este tema, que él vinculó desde este otro crtp via c# answer.
Todo eso dicho, si cambia la aplicación a este ...
public class TreeNode<T> where T : TreeNode<T>
{
public void AddChild(T a_node)
{
a_node.SetParent(this);
}
void SetParent(TreeNode<T> a_parent)
{
m_parent = a_parent;
}
TreeNode<T> m_parent;
}
... el código anterior que anteriormente arrojó el InvalidCastException
ahora trabaja.El cambio hace m_Parent
un tipo de TreeNode<T>
; haciendo this
ya sea del tipo T
como en el caso Foo
clase o una subclase de TreeNode<T>
en el caso Bar
clase ya Bar
hereda de TreeNode<Foo>
- de cualquier manera nos permite omitir el elenco en SetParent
y por esa omisión evitamos la excepción de difusión inválida ya que la la asignación es legal en todos los casos. El costo de hacer esto ya no puede usar libremente T
en todos los lugares como se había utilizado anteriormente, lo que sacrifica gran parte del valor de CRTP.
Un colega/amigo mío se considera un novato en un idioma/función de lenguaje hasta que honestamente puede decir que lo "usó con ira"; es decir, conoce el idioma lo suficientemente bien como para sentirse frustrado de que no hay forma de lograr lo que necesita o que hacerlo es doloroso. Esto muy bien podría ser uno de esos casos, ya que hay limitaciones y diferencias aquí que hacen eco de la verdad que generics are not templates.
Me permití simplificar su ejemplo. Por favor, invierte si no estás de acuerdo. – usr
Para ser sincero, esto parece una cabeza inteligente ** k. ¿Qué hay de malo con las formas más tradicionales de representar árboles usando composición en su lugar? ¿Qué te compra esto? Espero que eso no suene demasiado antagónico. Tengo curiosidad. – spender
@spender reduce a la mitad el número de asignaciones y reduce el número de indirecciones que debe seguir. Por lo tanto, en el código de alto rendimiento puede ser una compensación razonable. Para árboles más pequeños, probablemente sea una mala idea. – CodesInChaos