简体   繁体   中英

Instanced extension methods? C#

So I would like to create an extension method for a Type that the api has otherwise sealed.

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. I would like each GameObject to have its own list of Members. However Im pretty sure since this is a static field every instanced GameObject will point to the same static 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. 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.

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. There is a related answer on the UnityAnswers site that may help: 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.

Yes, you are right. If you have a static method, all instances of that class share the same data. The call return memberList; is illegal. It is the same as return this.memberList; and this is not available in a static method. Instead you'd have to call the class: 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.

Alternatively you could attach the memberList by using a dictionary of the form Dictionary<GameObject, List<Member>> . 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. 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.

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). 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. This will only work if you yourself are the one constructing these objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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