扩展方法如何工作?

时间:2016-02-25 13:33:30

标签: c# unity3d extension-methods

我想在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 个答案:

答案 0 :(得分:9)

首先,这里有一个非常快速的 扩展 教程,适合那些在Google上学习c#/ Unity的人:

制作一个像这样的新文本文件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()。您可以在任何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#中执行此操作。)

现在,如果你想要返回“那个东西”,你需要预先包含静态类名,而你不要把它作为扩展名。这只是对静态的正常调用。

...误

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类创建一个扩展方法[实际上是一个struct]

扩展只能在 实际变量 上调用,而不能在“类或结构”上调用。

   Vector3 hero;
   Vector3 enemy;
   hero.Jiggle();  // works great
   enemy.Jiggle();  // works great

   Vector3.Jiggle();  // syntax error - meaningless

另外请注意,正如Mikael在答案中提到的那样,事实上你实际上可以这样做:

  (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);,这是一个alpha值为.5f的pucey颜色。

我一直以为如果你问的语法可用会很好,如果你可以把某种“类型”或“类”作为你所延伸的“东西” - 但事实并非如此。对于你想要做的事情,你必须使用一个方便的词,比如,好吧,Handy,并且这样做

Vector3 big = 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
   }

在那个例子中,它只在大约三分之一的时间内完成。

(请注意,在可能的情况下,您通常会使扩展使用泛型。为简单起见,此处未显示。)

这是一个handy extension trick。这是一个非常advanced extension

扩展在Unity工程中无处不在。

如果你是学习使用Unity编码的众多人之一......你应该掌握的第一件事就是扩展。尝试使用扩展名几乎所有。有时在使用Unity时,几乎每行代码都需要一个或多个扩展。享受!

答案 1 :(得分:2)

扩展方法是一种使静态方法看起来像类或接口的一部分的方法。 Vector3上的扩展方法Foo()意味着你可以像你说的那样做新的Vector3()。Foo()。

看起来你希望你的MaxValue属性成为Vector3上的静态成员,扩展方法无法帮助你。无法将静态成员添加到现有类中。

但是,这真的有必要吗?您可以在新类型中定义常量属性。我们称之为“KnownVectors”或其他东西,然后去:

Vector3 closestPoint = KnownVectors.MaxValue;

当然,也许以某种方式把它变成现有的Vector3类会很好,但是它真的会在你的代码中添加任何内容吗?