c# - metodo - ¿Cómo funcionan los métodos de extensión?
metodos de extension c# (2)
Quiero hacer un método de extensión en Unity3d para la clase Vector3. Pero parece que no lo entiendo. Esto es lo que tengo:
public static class ExtensionMethods{
public static Vector3 MaxValue(this Vector3 _vec3)
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}
}
Ahora quiero hacer un
Vector3.MaxValue
como
float.MaxValue
con esta línea de código:
Vector3 closestPoint = Vector3.MaxValue;
Pero luego me sale este error:
error CS0117: `UnityEngine.Vector3'' does not contain a definition for `MaxValue''
Sé que esto funcionaría:
Vector3 closestPoint = new Vector3().MaxValue();
Pero luego creo 2 nuevas instancias de
Vector3
.
Uno en la llamada
MaxValue
y otro afuera.
¿No es posible hacer uno y hacerlo con este tipo de código:
Vector3 closestPoint = Vector3.MaxValue;
Los métodos de extensión son una forma de hacer que parezca que los métodos estáticos son parte de una clase o interfaz. Un método de extensión Foo () en Vector3 significa que puede hacer un nuevo Vector3 (). Foo () como usted dice.
Parece que le gustaría que su propiedad MaxValue sea un miembro estático en Vector3, y los métodos de extensión no pueden ayudarlo allí. No hay forma de agregar miembros estáticos a una clase existente.
¿Pero es realmente necesario? Simplemente puede definir su propiedad constante en un nuevo tipo. Llamémoslo "KnownVectors" o algo así, y vamos:
Vector3 closestPoint = KnownVectors.MaxValue;
Claro, tal vez sería bueno calzar esto en la clase Vector3 existente de alguna manera, pero ¿realmente agregaría algo a su código?
Primero, aquí hay un tutorial muy rápido sobre extensiones para aquellos que aprenden c # / Unity para cualquiera que busque en Google aquí:
Cree un nuevo archivo de texto
HandyExtensions.cs
como este ... (tenga en cuenta que, de manera algo confusa, puede usar
cualquier nombre
para la clase que "contiene" sus extensiones; el nombre real de la clase nunca se usa, y es irrelevante) ...
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public static class HandyExtensions
{
public static float Jiggled(this float ff)
{
return ff * Random.Range(0.9f,1.1f);
}
}
Ahora ha creado un nuevo "comando"
Jiggle()
.
Puedes usar jiggle en cualquier
float
.
Vea donde dice "this
float
ff".
Debido a que dice "flotante" justo allí, esta extensión funciona en flotantes.
Como puede ver, la extensión
Jiggled()
tomará un flotador y lo cambiará ligeramente.
Pruébalo así
float x = 3.5f;
Debug.Log("x is " + x);
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Debug.Log("x is " + x.Jiggled() );
Haga algunas pruebas como esa hasta que comprenda bien las extensiones. ¡Aprenda todo lo que pueda sobre las extensiones! Aquí hay another tutorial.
Y ahora la pregunta en esta página! ...
Como explica Mikael, lo que estás buscando no es en realidad una extensión. (También tenga en cuenta que si está intentando agregar un campo a Vector3, no puede hacerlo en c #).
Ahora, si desea devolver "esa cosa", debe incluir el nombre de la clase estática por adelantado, y NO lo convierta en una extensión. Es solo una llamada normal a una estática.
incorrecto...
public static Vector3 MaxValue(this Vector3 _vec3)
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}
correcto...
public static Vector3 MaxValue()
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}
entonces puedes hacer esto ...
Debug.Log( ExtensionMethods.MaxValue() );
Creo que eso puede ser lo que estás buscando allí.
Normalmente llamarías a
ExtensionMethods
algo corto como
Handy
para que puedas escribir
Handy.MaxValue();
de hecho, como no puede poner el "Vector3 por adelantado", algo como esto sería más claro:
Handy.MaxVector3();
¿tiene sentido?
Si está intentando escribir algo como esto:
Vector3.MaxValue()
no puede hacer eso ... porque la parte "Vector3"
ES UNA CLASE
(o Estructura), no una variable.
Por ejemplo, esta es una extensión en un entero:
375.Jiggle();
y esta es una extensión en un entero:
int x;
x.Jiggle();
pero esto no tiene sentido:
int.Jiggle(); // meaningless
Para repetir para mayor claridad, tenga en cuenta que preguntó:
Quiero hacer un método de extensión en Unity3d para la clase Vector3 [en realidad una estructura]
las extensiones solo se pueden invocar en variables reales , no en "la clase o estructura".
Vector3 hero;
Vector3 enemy;
hero.Jiggle(); // works great
enemy.Jiggle(); // works great
Vector3.Jiggle(); // syntax error - meaningless
Tenga en cuenta también que, como Mikael realmente menciona en su respuesta, de hecho puede hacer esto:
(new Vector3()).Jiggle();
Si lo piensas, eso también tiene sentido. Una de mis cosas favoritas en C # es que puede usar extensiones en constantes antiguas simples :
14.Jiggle();
7.5f.Radians();
Tienes que amar eso a menos que no obtengas placer de la vida. Aquí hay un ejemplo de eso:
public static Color Colored( this float alpha, int r, int g, int b )
{
return new Color(
(float)r / 255f,
(float)g / 255f,
(float)b / 255f,
alpha );
}
Luego puede escribir ...
Color c = .5f.Colored(.2f,.4f,.2f);
y ese es un color pucey con un alfa de .5f.
Siempre pensé que sería genial si la sintaxis sobre la que preguntas estaba disponible , si pudieras tener un "tipo" o "clase" de alguna manera como la "cosa" que extiendes, pero no es el caso. Para lo que está tratando de hacer, solo tiene que usar una palabra útil como, bueno, práctico, y hacer esto
Vector3 grande = Handy.MaxVec3 ();
¡Espero que esto explique la situación!
Nuevamente para cualquiera que necesite una introducción general a las extensiones, another . Estas son algunas de mis extensiones favoritas.
Algo como lo siguiente se usa en cada proyecto de juego ...
public static float Jiggle(this float ff)
{
return ff * UnityEngine.Random.Range(0.9f,1.1f);
}
public static float PositiveOrNegative(this float ff)
{
int r = UnityEngine.Random.Range(0,2);
if (r==0) return ff;
return -ff;
}
public static bool Sometimes(this int n)
{
if (n<=1) return true;
int r = UnityEngine.Random.Range(0,n);
return (r==0);
}
Ejemplo de usos ...
if ( 10.Sometimes() )
{
explode spaceship
}
solo lo hace una vez cada diez veces.
if ( 3.Sometimes() )
{
laser sparkle
}
en ese ejemplo solo lo hace aproximadamente un tercio del tiempo.
(Tenga en cuenta que, por lo general, las extensiones usan genéricos cuando es posible. No se muestran aquí por simplicidad)
Aquí hay un útil truco de extensión . Aquí hay una extensión realmente avanzada .
Las extensiones son ubicuas en la ingeniería de Unity.
Si eres una de las muchas personas que aprenden a codificar usando Unity ... más o menos lo primero que debes dominar son las extensiones. Intenta hacer casi todo con una extensión. A veces, cuando se trabaja con Unity, casi todas las líneas de código necesitan una o más extensiones. ¡Disfrutar!