Как работают методы расширения?
Я хочу сделать метод расширения в Unity3d для класса Vector3. Но я, кажется, не совсем понимаю. Вот что у меня есть:
public static class ExtensionMethods{
public static Vector3 MaxValue(this Vector3 _vec3)
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}
}
Теперь я хочу сделать Vector3.MaxValue
как float.MaxValue
с этой строкой кода:
Vector3 closestPoint = Vector3.MaxValue;
Но тогда я получаю эту ошибку:
error CS0117: `UnityEngine.Vector3' does not contain a definition for `MaxValue'
Я знаю, что это будет работать:
Vector3 closestPoint = new Vector3().MaxValue();
Но потом я создаю 2 новых Vector3
экземпляров. Один в MaxValue
позвони и один снаружи. Разве нельзя просто сделать один и сделать это с таким кодом:
Vector3 closestPoint = Vector3.MaxValue;
2 ответа
Во-первых, вот очень краткое руководство по расширениям для тех, кто изучает C#/Unity для тех, кто ищет в Google:
Создать новый текстовый файл HandyExtensions.cs
как это... (обратите внимание, что несколько запутанно, вы можете использовать любое имя вообще для класса, который "содержит" ваши расширения - фактическое имя класса никогда не используется вообще, и не имеет значения)...
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);
}
}
Вы сейчас сделали новую "команду" Jiggle()
, Вы можете использовать Jiggle на любом float
, Посмотрите, где написано "этот поплавок ". Поскольку там написано "float", это расширение работает на float.
Как видите, Jiggled()
Расширение возьмет поплавок и слегка его изменит. Попробуйте это так
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() );
Выполняйте подобные тесты, пока не разберетесь в расширениях. Узнайте как можно больше о расширениях! Вот еще один урок.
А теперь вопрос на этой странице!...
Как объясняет Микаэль, то, что вы ищете, на самом деле не является расширением. (Также обратите внимание, что если вы пытаетесь добавить поле в Vector3, вы не можете сделать это в C#.)
Теперь, если вы хотите вернуть "эту вещь", вам нужно включить статическое имя класса заранее, и вы НЕ делаете его расширением. Это просто обычный вызов статики.
неправильно...
public static Vector3 MaxValue(this Vector3 _vec3)
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}
правильный...
public static Vector3 MaxValue()
{
return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}
Вы можете сделать это...
Debug.Log( ExtensionMethods.MaxValue() );
Я думаю, что это может быть то, что вы ищете там.
Ты бы обычно звонил ExtensionMethods
что-то короткое, как Handy
так что вы можете написать
Handy.MaxValue();
действительно, поскольку вы не можете поставить "Vector3 на передний план", что-то вроде этого будет более понятным:
Handy.MaxVector3();
имеет смысл?
Если вы пытаетесь написать что-то вроде этого: Vector3.MaxValue()
Вы не можете сделать это... потому что часть "Vector3" является классом (или структурой), а не переменной. Например, это расширение на целое число:
375.Jiggle();
и это расширение на целое число:
int x;
x.Jiggle();
но это бессмысленно
int.Jiggle(); // meaningless
Чтобы повторить для ясности, обратите внимание, что вы спросили:
Я хочу сделать метод расширения в Unity3d для класса Vector3 [на самом деле структура]
расширения могут быть вызваны только для реальных переменных, а не для "класса или структуры".
Vector3 hero;
Vector3 enemy;
hero.Jiggle(); // works great
enemy.Jiggle(); // works great
Vector3.Jiggle(); // syntax error - meaningless
Заметьте также, что, как на самом деле упоминает Микаэль в своем ответе, вы на самом деле можете сделать это:
(new Vector3()).Jiggle();
Если подумать, это тоже имеет смысл. Одна из моих любимых вещей в C# заключается в том, что вы можете использовать расширения для простых старых констант:
14.Jiggle();
7.5f.Radians();
Вы должны любить это, если только вы не получаете никакого удовольствия от жизни. Вот пример этого:
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 );
}
Затем вы можете написать.. Color c = .5f.Colored(.2f,.4f,.2f);
и это буйный цвет с альфой.5f.
Я всегда думал, что было бы замечательно, если бы синтаксис, о котором вы спрашиваете, был доступен, если бы вы могли иметь "тип" или "класс" как-то как "вещь", на которую вы расширяете, - но это не так. Для того, что вы пытаетесь сделать, вы просто должны использовать удобное слово, например, Handy, и сделать это
Vector3 big = Handy.MaxVec3();
Я надеюсь, что это объясняет ситуацию!
Опять же для тех, кому нужно общее введение в расширения, введение. Вот некоторые из моих любимых расширений.
Нечто подобное используется в каждом игровом проекте...
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);
}
Пример использования..
if ( 10.Sometimes() )
{
explode spaceship
}
это происходит только один раз из десяти.
if ( 3.Sometimes() )
{
laser sparkle
}
в этом примере он делает это только около трети времени.
(Обратите внимание, что, как правило, вы делаете расширения, где это возможно, с использованием обобщений. Не показано здесь для простоты.)
Вот удобный трюк с расширением. Вот действительно продвинутое расширение.
Расширения вездесущи в Unity engineering.
Если вы один из многих, кто учится программировать с использованием Unity... в первую очередь вам нужно освоить расширения. Попробуйте сделать почти все с расширением. Иногда при работе с Unity почти каждой строке кода требуется одно или несколько расширений. Наслаждайтесь!
Методы расширения - это способ сделать так, чтобы статические методы были частью класса или интерфейса. Метод расширения Foo() в Vector3 означает, что вы можете сделать новый Vector3().Foo(), как вы сказали.
Похоже, вы хотите, чтобы ваше свойство MaxValue было статическим членом в Vector3, и методы расширения не могут вам помочь. Нет никакого способа добавить статические члены в существующий класс.
Но действительно ли это необходимо? Вы можете просто определить свое постоянное свойство в новом типе. Давайте назовем это "KnownVectors" или что-то в этом роде:
Vector3 closestPoint = KnownVectors.MaxValue;
Конечно, может быть, было бы неплохо вставить это в существующий класс Vector3, но действительно ли это добавит что-то в ваш код?