简体   繁体   English

实例扩展方法? C#

[英]Instanced extension methods? C#

So I would like to create an extension method for a Type that the api has otherwise sealed. 所以我想为api创建一个扩展方法,api已经密封了。

If you know about extension methods the following should look familiar. 如果您了解扩展方法,则以下内容应该很熟悉。

private static List<Member> memberList = new List<Member>();

public static List<Member> GetMemberList(this GameObject go)
{
    return memberList;
}

Notice that to declare an extension method, it needs to be static, and because it needs to be static, the List that Im accessing through the GameObject type has to be static to. 请注意,要声明扩展方法,它需要是静态的,并且因为它需要是静态的,所以我通过GameObject类型访问的List必须是静态的。 I would like each GameObject to have its own list of Members. 我希望每个GameObject都有自己的成员列表。 However Im pretty sure since this is a static field every instanced GameObject will point to the same static memberList. 但是我很确定,因为这是一个静态字段,每个实例GameObject都会指向相同的静态memberList。

So would my assumptions be true? 我的假设是真的吗? And if so, what might be an alternative? 如果是这样,可能会有什么替代方案? I would like to avoid putting the GameObject in a wrapper class that also holds the memberList because the api only allows GameObjects to be detected and manipulated at runtime. 我想避免将GameObject放在也包含memberList的包装类中,因为api只允许在运行时检测和操作GameObjects。 There are ways to reverse reference the wrapper class through the gameObject but that adds a lot more complexity to the code i would like to avoid. 有一些方法可以通过gameObject反向引用包装类,但这会增加我希望避免的代码的复杂性。

Yes, if you want to keep something outside the game object and access it through the extension method, it would have to be static. 是的,如果你想在游戏对象之外保留一些内容并通过扩展方法访问它,它必须是静态的。

You can use a dictionary to map one member list to each game object: 您可以使用字典将一个成员列表映射到每个游戏对象:

private static Dictionary<GameObject, List<Member>> memberLists = new Dictionary<GameObject, List<Member>>();

public static List<Member> GetMemberList(this GameObject go) {
  return memberLists[go];
}

It appears you are working with Unity3. 看来你正在使用Unity3。 There is a related answer on the UnityAnswers site that may help: http://answers.unity3d.com/questions/22493/unity-3-sealed-class-gameobject-.html UnityAnswers网站上有一个相关的答案可能有所帮助: http ://answers.unity3d.com/questions/22493/unity-3-sealed-class-gameobject-.html

It appears that there should be ways to attach the behaviors you want inherent in the Unity framework using the builtin scripting system. 似乎应该有办法使用内置脚本系统附加您想要的Unity框架中固有的行为。

Yes, you are right. 是的,你是对的。 If you have a static method, all instances of that class share the same data. 如果您有静态方法,则该类的所有实例共享相同的数据。 The call return memberList; 调用return memberList; is illegal. 是非法的。 It is the same as return this.memberList; 它与return this.memberList;相同return this.memberList; and this is not available in a static method. this在静态方法中不可用。 Instead you'd have to call the class: return GameObject.memberList; 相反,你必须调用该类: return GameObject.memberList; . But I understand that you are not looking for this solution. 但我知道你不是在寻找这个解决方案。

Extension methods are meant to create additional behavior . 扩展方法旨在创建其他行为 If you want to create additional data , extending the GameObject class using inheritance is the right choice. 如果要创建其他数据 ,则使用继承扩展GameObject类是正确的选择。

Alternatively you could attach the memberList by using a dictionary of the form Dictionary<GameObject, List<Member>> . 或者,您可以使用Dictionary<GameObject, List<Member>>形式的Dictionary<GameObject, List<Member>>附加memberList。 But personally I'd favor composition as shown below: 但我个人赞成如下所示的作文:

public class myGameObject
{
    public List<Member> memberList { get; set; }
    public GameObject go { get; set; }
}
private static ConditionalWeakTable<GameObject, List<Member>> dict = new ConditionalWeakTable<GameObject, List<Member>>();

public static List<Member> GetMemberList(this GameObject go)
{
  return dict.GetOrCreateValue(go);
}

ConditionalWeakTable manages the object lifetime, because it uses weak-references. ConditionalWeakTable管理对象生存期,因为它使用弱引用。 Therefore it doesn't stop the GC from collecting the GameObject if it there are no other live references to it, and this will also allow the List<Member> to be collected. 因此,如果没有其他实时引用,它不会阻止GC收集GameObject ,这也将允许收集List<Member>

It is threadsafe, but this assumes that you want your starting point to be an empty list (the default constructor is called in GetOrCreateValue if there isn't a current value). 它是线程安全的,但是这假设你希望你的起始点是一个空列表(如果没有当前值,则在GetOrCreateValue调用默认构造函数)。 If you want a different starting point, your threading issues become more complicated. 如果您想要一个不同的起点,您的线程问题会变得更加复杂。

Extension methods are simply just static methods that "appear" to look like instance methods. 扩展方法只是“看起来”像实例方法的静态方法。

They however, do not add any additional functionality a static method doesn't, it's just for ease-of-use, maintenance, and readability. 但是,它们不会添加静态方法所没有的任何附加功能,它只是为了易用性,维护和可读性。 Extension methods cannot access protected / private members either. 扩展方法也无法访问受保护/私有成员。

If GameObject is not actually sealed (ie it doesn't have the sealed keyword), then you can write a class that inherits GameObject to gain access to its protected methods/fields/properties. 如果GameObject实际上没有密封(即它没有sealed关键字),那么您可以编写一个继承GameObject的类来访问其受保护的方法/字段/属性。 This will only work if you yourself are the one constructing these objects. 这只有在您自己构建这些对象的情况下才有效。

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

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