[Unity] Unity development advanced (seven) double-edged sword: extension method


extension method

C# introduced "extension methods" in version 3.0, which not only has the advantages of static methods, but also improves the readability of the code that calls them. When using extension methods, static methods can be called just like instance methods.

extension method declaration

  1. Must be in a non-nested, non-generic static class (so must be a static method).
  2. There is at least one parameter.
  3. The first parameter must be prefixed with the this keyword.
  4. The first parameter cannot have any other modifiers (such as ref or out).
  5. The type of the first parameter cannot be a pointer type.

how to use

The extension method parameter can add a method to the type of the parameter. Simply put, if you write a method in class A, class B will also have this method. for example:

public static class A
{
    
    
    public static void Foo(this B s)
    {
    
    
    }
}

class B
{
    
    
}

class MainClass
{
    
    
	static void Main()
    {
    
    
        B b = new B();
        // 使用B类的对象调用A类中定义的Foo方法
        b.Foo();          
    }
}

The object b in the code can directly call the Foo method, because this method has been extended to the B class.

for example

I want to make a tool class (TransformHelper) for assisting the Transform class. One of the methods is to recursively find a transformation component in the sub-object. At this time, you can pass **this parameter (extension method)** to give Add this method to the Transform class, the code is as follows:

/// <summary>
///变换组件助手类
/// </summary>
public static class TransformHelper
{
    
    
    /// <summary>
    /// 递归查找变换组件
    /// </summary>
    /// <param name="cuurentTF">当前对象</param>
    /// <param name="childName">要查找的子节点名称</param>
    /// <returns></returns>
    public static Transform FindChildByName(this Transform cuurentTF, string childName)
    {
    
    
        Transform child = cuurentTF.Find(childName);

        if (child != null) return child;

        for (int i = 0; i < cuurentTF.childCount; i++)
        {
    
    
            child = FindChildByName(cuurentTF.GetChild(i), childName);
            if (child != null) return child;
        }

        return null;
    }
}

/// <summary>
/// 游戏主窗口
/// </summary>
public class UIMainWindow : MonoBehaviour
{
    
    
    private void Start()
    {
    
    
        // 用静态类的方式调用方法
        TransformHelper.FindChildByName(transform, "ButtonGameStart").GetComponent<Button>().onClick.AddListener(OnGameStartButtonClick);
        
        // 直接使用变化组件调用方法,注意,此时不用要再传第一个参数了,因为第一个参数已经成为默认的this了。
        transform.FindChildByName("ButtonGameStart").GetComponent<Button>().onClick.AddListener(OnGameStartButtonClick);
    }
}

The basic principle

  1. C# only supports extension methods, and does not support extension properties, extension events, extension operators, etc.
  2. An extension method (a method whose first parameter is preceded by this) must be declared in a non-generic static class. The extension method must have one parameter, and only the first parameter uses the this mark.
  3. When the C# compiler looks for extension methods in static classes, it requires that the static classes themselves must have file scope.
  4. C# compilation requires "importing" the extension method. (Static methods can be named arbitrarily. When the C# compiler is looking for methods, it takes time to find them. It needs to check all static classes in the file scope and scan all their static methods to find a match).
  5. Multiple static classes can define the same extension method.
  6. When a type is extended with an extension method, the derived type is also extended.
  7. There is no need to pass the first parameter when calling the method, and the object (this) of the calling method is specified as the first parameter by default.

Pros and Cons of Extension Methods

When I first came into contact with the extension method, I always felt that it was unreasonable, because the extension method may cause each class to have new, hidden, and unknown methods. First, it is unreasonable to consider from the perspective of memory (Question 1 ), and secondly, it is quite difficult to consider the maintainability and ease of use of the code ( question 2 ).

For example, if I extend the method to generics, the code is as follows:

public static string FindKey<T>(this T obj, FindHandler<T> handler)
{
    
    
    return null;
}

According to normal understanding, it is thought that all types, or all types introduced into this class, will add the FindKey method, but this is not the case, or not entirely. Although these methods can be called directly using the object, the original static method is actually called instead of the method rewritten into the generic T class.

Why do you say that?

Because the Attribute ExtensionAttribute will be used in the extension method . Once the first parameter of a static method is marked with the this keyword, the compiler will internally apply a custom attribute to the method, and this attribute will be stored persistently in the metadata of the final generated file . This attribute is in the System.Core dll assembly.

As long as any static class contains at least one extension method, this attribute will also be applied to its metadata. Any assembly that contains at least one static class that meets the above characteristics will also apply this attribute to its metadata. If the code uses an instance method that does not exist, the compiler will quickly scan all referenced assemblies to determine which ones contain extension methods . Then, in this assembly, it can scan static classes that contain extension methods .

If two classes in the same namespace contain methods that extend the same type, there is no way to use the extension method from only one of the classes. In order to use a type by its simple name (without the namespace prefix), it is possible to import all namespaces in which that type exists, but in doing so, you have no way to prevent extension methods in that namespace from being imported as well.

Back to the original question:

Question 1: Is this extension method added to every object?
This problem did not actually happen, because the way C# uses is not to add a method to each object, but to provide a list of extension methods. When using the list, find the extended static method and call it, that is to say, the method There is still only that one method, and it does not occupy a large area of ​​the method area.

Question 2: Has the maintainability and ease of use of the code been affected?
This problem actually exists. If the development team cannot effectively control the definition of the extension method, there will be problems where partial codes cannot be traced or the extension function affects the main scene function, resulting in poor code readability and unclear semantics. However, if the development team can effectively control the creation of extension methods and provide a dedicated extension method maintenance and usage plan, the development efficiency will also be slightly improved.

Summarize

The extension method can be said to be a double-edged sword. It is extremely sharp if it is used well, and it may cause self-injury if it is not used well.


Part of this article quotes the blog provided by Peng Ze0902: Related Links

For more information, please check the general catalog [Unity] Unity study notes catalog arrangement

Guess you like

Origin blog.csdn.net/xiaoyaoACi/article/details/126078926