¿Se pueden agregar métodos de extensión a una estructura?Métodos de extensión en una estructura
Respuesta
Sí, puede agregar métodos de extensión en las estructuras. Según la definición del método de extensión, puede lograrlo fácilmente. A continuación se muestra un ejemplo del método de extensión en int
namespace ExtensionMethods
{
public static class IntExtensions
{
public static bool IsGreaterEqualThan(this int i, int value)
{
return i >= value;
}
}
}
Sin embargo, tenga cuidado con esto, ya que la estructura se pasa al método de extensión POR VALOR (como se quiere hacer con las estructuras). Por lo tanto, cualquier modificación que haga a la estructura en el método de extensión se perderá, a menos que devuelva la estructura del curso (y luego haga algo con esa estructura pasada, como reasignarla a sí misma). No hay forma de hacer un método de extensión en una estructura y hacer que se pase por referencia (en C#). – BrainSlugs83
Parece que no puedo extender System.Drawing.Rectangle que también es una estructura, y está decorado con Serializable y ComVisible y TypeConverter. – zionpi
Es posible agregar métodos de extensión a las estructuras, pero hay una advertencia importante. Los métodos de métodos de estructura normales aceptan this
como un parámetro ref
, pero C# no permitirá la definición de métodos de extensión que lo hagan. Si bien los métodos struct que cambian this
pueden ser algo peligrosos (dado que el compilador permitirá que los métodos struct se invoquen en estructuras de solo lectura, pero pase this
por valor), a veces también pueden ser útiles si se tiene cuidado de asegurarse de que sean solo se usa en contextos apropiados.
A propósito, vb.net permite que los métodos de extensión acepten this
como un parámetro ByRef
, ya sea una clase, estructura o un genérico de categoría desconocida. Esto puede ser útil en algunos casos donde las interfaces pueden ser implementadas por estructuras. Por ejemplo, si se intenta invocar en una variable del tipo List<string>.Enumerator
un método de extensión que toma un parámetro this
del tipo IEnumerator<string>
, o toma por valor un parámetro this
de un genérico restringido a IEnumerator<string>
, y si el método intenta avanzar al enumerador, cualquier avance se deshará cuando regrese el método. Sin embargo, un método de extensión que toma un genérico restringido por referencia (posible en vb.net) se comportará como debería.
Entonces, ¿qué podría ser un ejemplo de usar uno en C#? 'public static Rect CreateRectFromPercents (this Rect rect)' por ejemplo no funciona. – MichaelTaylor3D
@ MichaelTaylor3D: ¿Qué es 'Rect'? ¿Quiere decir 'System.Drawing.Rectangle' o algún tipo personalizado? – supercat
es una estructura que es parte de mi uso de API. Solo lo estaba usando como un ejemplo. La API me impide modificarla directamente, así que esperaba usar un método de extensión. He leído que es posible para las estructuras pero aún no he visto un ejemplo. Tu explicación es lo más cercano que puedo encontrar. – MichaelTaylor3D
Sí, puede definir un método de extensión en un tipo de estructura/valor. Sin embargo, no tienen el mismo comportamiento que los métodos de extensión en los tipos de referencia.
Por ejemplo, el método de extensión GetA() en el siguiente código C# recibe una copia de la estructura, no una referencia a la estructura. Esto significa que un método de extensión C# en una estructura no puede modificar el contenido original de la estructura.
public static class TestStructExtensionMethods {
public struct FooStruct {
public int a;
}
public static int GetA(this FooStruct st) {
return st.a;
}
}
Para modificar el contenido de la estructura, el struct paramater debe declararse como "ref". Sin embargo, "esta referencia" no está permitida en C#. Lo mejor que podemos hacer es un método no estático como extensión:
// this works, but is inefficient, because it copies the whole FooStruct
// just to return a
public static int GetA(ref FooStruct st) {
return st.a;
}
En VB.NET, puede crear esto como un método de extensión ByRef estructura, por lo que podría modificar la estructura original de:
' This is efficient, because it is handed a reference to the struct
<Extension()> _
Public Sub GetA(ByRef [me] As FooStruct) As Integer
Return [me].a
End Sub
' It is possible to change the struct fields, because we have a ref
<Extension()> _
Public Sub SetA(ByRef [me] As FooStruct, newval As Integer)
[me].a = newval
End Sub
Ese VB.NET permite que los métodos de extensión acepten estructuras por 'ref' sería una buena cosa, pero por el hecho de que VB copiará silenciosamente cosas que' ref' no pueden pasar y pasará las copias en lugar de los originales. Si hubiera una manera de decirle a VB.NET que no hiciera eso (el código debería en cambio negarse a compilar), dichos métodos de extensión serían semánticamente superiores a los métodos de instancias struct que modifican 'this'. No sé por qué MS no proporciona ningún medio por el cual los métodos puedan indicar si deberían ser invocables en las estructuras temporales generadas por el compilador. – supercat
"... pero por el hecho de que VB copiará silenciosamente cosas que no pueden pasarse por ref y pasará las copias en lugar de los originales" - ¿cuándo lo hace VB? - "byref" se compila con el mismo código IL que "ref" en C# - mi entendimiento es que cualquier cosa puede pasar por ref en .NET - las únicas cosas que se copian son los tipos de valor (y solo cuando ellos no son aprobados por ref). – BrainSlugs83
@ BrainSlugs83: Intente pasar una propiedad de lectura/escritura por referencia en VB.net. Esa propiedad es simplemente el valor de retorno de la función getter, no una variable ... por lo que pasar por referencia no funciona. C# no lo permitirá. En lugar de eso, VB modificará el paso por referencia copiando el valor y pasando la * copia * por referencia ... luego, cuando la función vuelva, establecerá la propiedad en el nuevo valor. Lo cual * en su mayoría * funciona, y mantiene las propiedades translúcidas, si sigue LoD y mantiene las estructuras inmutables ... pero puede romperse de maneras semi-sorprendentes cuando los sub-objetos y los tipos de valores mutables se involucran. – cHao
Para futuros Googlers (y Bingers), aquí hay un código para extender una estructura. Este ejemplo convierte el valor en un tipo double
.
public static class ExtensionMethods {
public static double ToDouble<T>(this T value) where T : struct {
return Convert.ToDouble(value);
}
}
Después de ello se puede utilizar como ToDouble()
utiliza ToString()
. Tenga cuidado con los elementos de conversión como desbordamientos.
- 1. ¿Métodos de extensión en una clase estática?
- 2. métodos de extensión en T4
- 3. ¿Métodos de extensión virtual?
- 4. Métodos de extensión en Python
- 5. métodos de extensión estáticas
- 6. ¿Los métodos LINQ son métodos de extensión?
- 7. Métodos de extensión de enumeración
- 8. Métodos oficiales de extensión LINQ
- 9. Reemplazando los métodos de extensión
- 10. Organización de métodos de extensión
- 11. Métodos de extensión de encadenamiento en C#
- 12. Métodos de extensión no reconocidos
- 13. Métodos de extensión IEnumerable en un Enum
- 14. C# métodos de extensión similares en PHP?
- 15. C# métodos de extensión ambiguos
- 16. Métodos de extensión F # en C#
- 17. "Métodos de extensión" en Objective-C
- 18. ¿Utiliza métodos de extensión en .NET 2.0?
- 19. Mejores prácticas: C# Espacio de nombres de métodos de extensión y promoción de métodos de extensión
- 20. Uso de IoC en los métodos de extensión
- 21. Estructura en una estructura
- 22. burlando de métodos de extensión con Moq
- 23. Métodos de extensión de expresión RDLC
- 24. Métodos de extensión estática en el módulo Seq
- 25. Métodos de extensión vs Static Utility Class
- 26. ¿Qué son los métodos de extensión?
- 27. C# Métodos de extensión - patrones de diseño
- 28. ¿Puedo agregar métodos de extensión a una clase estática existente?
- 29. C#: operador implícito y métodos de extensión
- 30. ¿Cómo agrupar los métodos de extensión?
¿Has intentado agregar un método de extensión en una estructura? Tenga en cuenta que no debe eliminar preguntas cuando encuentre la respuesta a ellas, otros podrían preguntarse sobre lo mismo. Y sí, puede declararlos, pero cambiar las cosas en la estructura no funcionará como espera, a menos que espere que no funcione. –
Sí, lo intenté pero no funcionó. –
Gracias funcionó, mi error –