扩展方法如何工作?
How do extension methods work?
我想在 Unity3d 中为 Vector3 创建一个扩展方法 class。但我似乎不太明白。这是我的:
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;
扩展方法是一种使静态方法看起来像是 class 或接口的一部分的方法。 Vector3 上的扩展方法 Foo() 意味着您可以像您说的那样执行 new Vector3().Foo()。
您似乎希望 MaxValue 属性 成为 Vector3 上的静态成员,而扩展方法对此无能为力。无法将静态成员添加到现有 class.
但是,真的有必要吗?您可以在新类型中定义常量 属性 。我们称它为 "KnownVectors" 或其他名称,然后:
Vector3 closestPoint = KnownVectors.MaxValue;
当然,也许以某种方式将其硬塞到现有的 Vector3 class 中会很好,但它真的会为您的代码添加任何内容吗?
首先,这里有一个非常快速的扩展教程,适用于那些学习 c#/Unity 的人,任何在这里谷歌搜索的人:
像这样创建一个新的文本文件 HandyExtensions.cs
...(请注意,您可以使用 任何名称 作为 class它“保留”了您的扩展 - class 的实际名称从未被使用过,并且无关紧要)...
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()
。您可以在任何 float
上使用微动。看看它在哪里写着“this float ff”。因为它就在那里说“浮动”,所以这个扩展适用于浮动。
如您所见,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() );
做一些这样的测试,直到你对扩展有了很好的理解。尽可能多地了解扩展!这是 another 教程。
现在这个页面上的问题! ...
正如 Mikael 所解释的,您正在寻找的实际上并不是扩展。 (另请注意,如果您尝试 添加一个字段 到 Vector3,则不能在 c# 中执行此操作。)
现在,如果你想return“那个东西”,你需要在前面包含静态class名称,而且你不要它是一个扩展。这只是对静态的正常调用。
错了...
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”部分是一个CLASS(或结构),不是变量。例如,这是一个整数的扩展:
375.Jiggle();
这是整数的扩展:
int x;
x.Jiggle();
但这没有意义:
int.Jiggle(); // meaningless
为了清楚起见,请重复一遍,请注意您问的是:
I want to make an extension method in Unity3d for the Vector3 class [actually a struct]
扩展只能在实际变量上调用,不能在“class或结构”上调用。
Vector3 hero;
Vector3 enemy;
hero.Jiggle(); // works great
enemy.Jiggle(); // works great
Vector3.Jiggle(); // syntax error - meaningless
另请注意,正如 Mikael 在他的回答中实际提到的那样,您实际上可以这样做:
(new Vector3()).Jiggle();
如果您考虑一下,这也是有道理的。在 C# 中我最喜欢的事情之一是你可以使用扩展 on plain old constants:
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);
,这是一种 alpha 为 .5f 的深色。
我一直认为如果你问的语法可用,如果你能以某种方式有一个“类型”或“class”就好了作为您扩展的“事物”-但事实并非如此。对于您要尝试做的事情,您只需使用一个方便的词,例如,嗯,Handy,然后执行此操作
Vector3 大 = Handy.MaxVec3();
我希望这能说明情况!
同样对于需要扩展的一般介绍的任何人,intro。这是我最喜欢的一些扩展程序。
在每个游戏项目中都会使用类似下面的内容...
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
}
在那个例子中,它只有大约三分之一的时间这样做。
(请注意,实际上通常您会尽可能使用泛型进行扩展。为简单起见,此处未显示。)
这是一个. Here's a really 。
扩展在 Unity 工程中无处不在。
如果您是众多学习使用 Unity 编码的人中的一员...您应该掌握的第一件事几乎就是扩展。尝试使用扩展名几乎所有。有时在使用 Unity 时,几乎每一行代码都需要一个或多个扩展。享受吧!
我想在 Unity3d 中为 Vector3 创建一个扩展方法 class。但我似乎不太明白。这是我的:
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;
扩展方法是一种使静态方法看起来像是 class 或接口的一部分的方法。 Vector3 上的扩展方法 Foo() 意味着您可以像您说的那样执行 new Vector3().Foo()。
您似乎希望 MaxValue 属性 成为 Vector3 上的静态成员,而扩展方法对此无能为力。无法将静态成员添加到现有 class.
但是,真的有必要吗?您可以在新类型中定义常量 属性 。我们称它为 "KnownVectors" 或其他名称,然后:
Vector3 closestPoint = KnownVectors.MaxValue;
当然,也许以某种方式将其硬塞到现有的 Vector3 class 中会很好,但它真的会为您的代码添加任何内容吗?
首先,这里有一个非常快速的扩展教程,适用于那些学习 c#/Unity 的人,任何在这里谷歌搜索的人:
像这样创建一个新的文本文件 HandyExtensions.cs
...(请注意,您可以使用 任何名称 作为 class它“保留”了您的扩展 - class 的实际名称从未被使用过,并且无关紧要)...
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()
。您可以在任何 float
上使用微动。看看它在哪里写着“this float ff”。因为它就在那里说“浮动”,所以这个扩展适用于浮动。
如您所见,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() );
做一些这样的测试,直到你对扩展有了很好的理解。尽可能多地了解扩展!这是 another 教程。
现在这个页面上的问题! ...
正如 Mikael 所解释的,您正在寻找的实际上并不是扩展。 (另请注意,如果您尝试 添加一个字段 到 Vector3,则不能在 c# 中执行此操作。)
现在,如果你想return“那个东西”,你需要在前面包含静态class名称,而且你不要它是一个扩展。这只是对静态的正常调用。
错了...
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”部分是一个CLASS(或结构),不是变量。例如,这是一个整数的扩展:
375.Jiggle();
这是整数的扩展:
int x;
x.Jiggle();
但这没有意义:
int.Jiggle(); // meaningless
为了清楚起见,请重复一遍,请注意您问的是:
I want to make an extension method in Unity3d for the Vector3 class [actually a struct]
扩展只能在实际变量上调用,不能在“class或结构”上调用。
Vector3 hero;
Vector3 enemy;
hero.Jiggle(); // works great
enemy.Jiggle(); // works great
Vector3.Jiggle(); // syntax error - meaningless
另请注意,正如 Mikael 在他的回答中实际提到的那样,您实际上可以这样做:
(new Vector3()).Jiggle();
如果您考虑一下,这也是有道理的。在 C# 中我最喜欢的事情之一是你可以使用扩展 on plain old constants:
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);
,这是一种 alpha 为 .5f 的深色。
我一直认为如果你问的语法可用,如果你能以某种方式有一个“类型”或“class”就好了作为您扩展的“事物”-但事实并非如此。对于您要尝试做的事情,您只需使用一个方便的词,例如,嗯,Handy,然后执行此操作
Vector3 大 = Handy.MaxVec3();
我希望这能说明情况!
同样对于需要扩展的一般介绍的任何人,intro。这是我最喜欢的一些扩展程序。
在每个游戏项目中都会使用类似下面的内容...
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 工程中无处不在。
如果您是众多学习使用 Unity 编码的人中的一员...您应该掌握的第一件事几乎就是扩展。尝试使用扩展名几乎所有。有时在使用 Unity 时,几乎每一行代码都需要一个或多个扩展。享受吧!