简体   繁体   English

扩展方法如何工作?

[英]How do extension methods work?

I want to make an extension method in Unity3d for the Vector3 class. 我想在Unity3d中为Vector3类创建一个扩展方法。 But I don't quite seem to get it. 但是我似乎不太明白。 This is what I have: 这就是我所拥有的:

public static class ExtensionMethods{

    public static Vector3 MaxValue(this Vector3 _vec3)
    {
        return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
    }
}

Now I want to make a Vector3.MaxValue just like float.MaxValue with this line of code: 现在,我想使用以下代码行来制作一个与Vector3.MaxValue一样的float.MaxValue

Vector3 closestPoint = Vector3.MaxValue;

But then I get this error: 但是然后我得到这个错误:

error CS0117: `UnityEngine.Vector3' does not contain a definition for `MaxValue'

I know that this would work: 我知道这会起作用:

Vector3 closestPoint = new Vector3().MaxValue();

But then I create 2 new Vector3 instances. 但是,然后我创建了两个新的Vector3实例。 One in the MaxValue call and one outside. 一个在MaxValue调用中,一个在外部。 Isn't it possible to just make one and do it with this kind of code: 用这样的代码编写一个代码是不可能的:

Vector3 closestPoint = Vector3.MaxValue;

First, here's a very quick tutorial on extensions for those learning c#/Unity for anyone googling here: 首先,这是一个有关扩展的快速教程,适用于那些在这里使用Google搜索的人学习c#/ Unity:

Make a new text file HandyExtensions.cs like this ... (note that somewhat confusingly, you can use any name at all for the class which "holds" your extensions - the actual name of the class is never used at all, and is irrelevant) ... 像这样创建一个新的文本文件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);
         }
     }

You have now made a new "command" Jiggle() . 现在,您已经创建了一个新的“命令” Jiggle() You can use jiggle on any float . 您可以在任何float上使用微动。 See where it says "this float ff". 看到它说“ this float ff”的地方。 Because it says "float" just there, this extension works on floats. 由于该扩展名仅在此处显示“ float”,因此该扩展程序适用于float。

As you can see, the Jiggled() extension will take a float and change it slightly. 如您所见, Jiggled()扩展名将采用浮点数并对其稍作更改。 Try it like this 像这样尝试

 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() );

Do some tests like that until you have a good understanding of extensions. 像这样进行一些测试,直到您对扩展有了很好的了解。 Learn as much as you can about extensions! 尽可能多地了解扩展! Here's another tutorial. 这是另一个教程。

And now the question on this page! 现在,此页面上的问题! ... ...


As Mikael explains, what you are looking for is not actually an extension. 正如Mikael解释的那样,您要寻找的实际上不是扩展。 (Also note, if you're trying to add a field to Vector3, you cannot do that in c#.) (还请注意,如果您尝试向Vector3 添加字段 ,则无法在c#中执行此操作。)

Now, if you want to return "that thing" you need to include the static class name up front, and you DO NOT make it an extension. 现在,如果要返回“那个东西”,则需要在前面包含静态类名 ,而不必将其扩展。 It's just a normal call to a static. 这只是对static的普通调用。

wrong... 错误...

public static Vector3 MaxValue(this Vector3 _vec3)
{
    return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}

correct... 正确...

public static Vector3 MaxValue()
{
    return new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
}

you can then do this ... 然后,您可以执行此操作...

Debug.Log(   ExtensionMethods.MaxValue()  );

I think that may be what you're looking for there. 我认为那可能是您在那寻找的东西。

You'd normally call ExtensionMethods something short like Handy so you can write 通常,您可以将ExtensionMethods称为Handy之类的简短名称,以便编写

 Handy.MaxValue();

indeed, since you can't put the "Vector3 up front", something like this would be more clear: 实际上,由于您不能将“ Vector3”放在前面,因此类似以下内容会更清楚:

  Handy.MaxVector3();

makes sense? 说得通?

If you're trying to write something like this: Vector3.MaxValue() you can't do that ... because the "Vector3" part IS A CLASS (or Struct), not a variable. 如果您尝试编写如下代码: Vector3.MaxValue() ,则无法执行此操作,因为“ Vector3”部分是CLASS (或Struct),而不是变量。 For example, this is an extension on an integer: 例如,这是整数的扩展:

 375.Jiggle();

and this is an extension on an integer: 这是整数的扩展:

 int x;
 x.Jiggle();

but this is meaningless: 但这是没有意义的:

 int.Jiggle();  // meaningless

To repeat for clarity, note that you asked: 为了清楚起见,请重复以下步骤:

I want to make an extension method in Unity3d for the Vector3 class [actually a struct] 我想在Unity3d中为Vector3类[实际上是一个结构]扩展方法

extensions can only be called on actual variables , not on "the class or struct". 扩展只能在实际变量上调用,而不能在“类或结构”上调用。

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

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

Note too that as Mikael actually mentions in his answer, you can in fact actually do this: 还要注意,正如Mikael在其答案中实际上提到的那样,您实际上可以这样做:

  (new Vector3()).Jiggle();

If you think about it that makes sense, too. 如果您考虑一下,这也是有道理的。 One of my favorite things in c# is that you can use extensions on plain old constants : 在C#中我最喜欢的事情之一是您可以在普通的旧常量上使用扩展名:

 14.Jiggle();
 7.5f.Radians();

You've got to love that unless you just get no pleasure from life. 您必须爱上它,除非您从生活中获得一点乐趣。 Here's an example of that: 这是一个例子:

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 );
    }

You can then write .. Color c = .5f.Colored(.2f,.4f,.2f); 然后,您可以编写.. Color c = .5f.Colored(.2f,.4f,.2f); and that is a pucey color with an alpha of .5f. 这是具有0.5f的alpha的浅绿色。

I've always thought it would be great if the syntax you ask about was available , if you could have a "type" or "class" somehow as the "thing" you extend on - but it's not the case. 我一直认为,如果您所要求的语法可用 ,并且可以像扩展您的“东西”一样拥有“类型”或“类”,那就太好了,但事实并非如此。 For what you are trying to do, you have to just use a handy word such as, well, Handy, and do this 对于您想做的事情,您只需要使用一个方便的单词,例如,好用,就可以了

Vector3 big = Handy.MaxVec3(); Vector3 big = Handy.MaxVec3();

I hope this explains the situation! 我希望这可以解释情况!


Again for anyone needing a general intro to extensions, intro . 对于需要扩展的一般介绍的任何人,再次介绍intro Here are some of my favorite extensions. 这是一些我最喜欢的扩展。

Something like the following is used in every game project... 每个游戏项目中都使用类似以下内容的东西:

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);
    }

Example uses.. 示例用途

 if ( 10.Sometimes() )
   {
   explode spaceship
   }

it only does it once in ten times. 它只会做十次。

 if ( 3.Sometimes() )
   {
   laser sparkle
   }

in that example it only does it about a third of the time. 在该示例中,它只执行大约三分之一的时间。

(Note that indeed typically you make extensions use generics where possible. Not shown here for simplicity.) (请注意,实际上,通常您会在可能的情况下使扩展使用泛型。为简单起见,此处未显示。)

Here's a handy extension trick . 这是一个方便的扩展技巧 Here's a really advanced extension . 这是一个非常高级的扩展

Extensions are ubiquitous in Unity engineering. 扩展在Unity工程中无处不在。

If you are one of the many folks learning to code using Unity...pretty much the first thing you should master is extensions. 如果您是学习使用Unity进行编码的众多人之一,那么您应该掌握的第一件事就是扩展。 Try to do almost everything with an extension. 尝试使用扩展程序执行几乎所有操作 Sometimes when working with Unity, almost every line of code needs one or more extensions. 有时,在使用Unity时,几乎每一行代码都需要一个或多个扩展。 Enjoy! 请享用!

Extension methods is a way to make it look like static methods are part of a class or interface. 扩展方法是一种使其看起来像静态方法是类或接口的一部分的方法。 An extension method Foo() on Vector3 means you can do new Vector3().Foo() just like you say. Vector3的扩展方法Foo()意味着您可以像说的那样创建新的Vector3()。Foo()。

It looks like you'd like your MaxValue property to be a static member on Vector3, and extension methods can't help you there. 您似乎希望MaxValue属性成为Vector3上的静态成员,而扩展方法无法为您提供帮助。 There's no way to add static members to an existing class. 无法将静态成员添加到现有类。

But, is it really necessary? 但是,真的有必要吗? You can just define your constant property in a new type. 您可以只在新类型中定义常量属性。 Let's call it "KnownVectors" or something, and go: 让我们称之为“ KnownVectors”之类,然后去:

Vector3 closestPoint = KnownVectors.MaxValue;

Sure, maybe it would be nice to shoehorn this into the existing Vector3 class somehow, but would it really add anything to your code? 当然,以某种方式将它塞入现有的Vector3类中可能会很好,但是会真的在代码中添加任何内容吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM