Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
实例扩展方法?C#_C#_Extension Methods - Fatal编程技术网

实例扩展方法?C#

实例扩展方法?C#,c#,extension-methods,C#,Extension Methods,因此,我想为api密封的类型创建一个扩展方法 如果您了解扩展方法,那么下面的内容应该很熟悉 private static List<Member> memberList = new List<Member>(); public static List<Member> GetMemberList(this GameObject go) { return memberList; } private static List memberList=new

因此,我想为api密封的类型创建一个扩展方法

如果您了解扩展方法,那么下面的内容应该很熟悉

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

public static List<Member> GetMemberList(this GameObject go)
{
    return memberList;
}
private static List memberList=new List();
公共静态列表GetMemberList(此游戏对象go)
{
返回成员列表;
}
请注意,要声明扩展方法,它必须是静态的,因为它必须是静态的,所以Im通过GameObject类型访问的列表必须是静态的。 我希望每个游戏对象都有自己的成员列表。不过,我很确定,因为这是一个静态字段,所以每个实例化的游戏对象都会指向同一个静态成员列表


那么我的假设是真的吗?如果是的话,还有什么替代方案?我希望避免将游戏对象放在一个也包含成员列表的包装类中,因为api只允许在运行时检测和操作游戏对象。有很多方法可以通过gameObject反向引用包装器类,但这会给我想要避免的代码增加更多的复杂性。

是的,如果您想在game对象之外保留一些内容并通过扩展方法访问它,那么它必须是静态的

您可以使用字典将一个成员列表映射到每个游戏对象:

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

public static List<Member> GetMemberList(this GameObject go) {
  return memberLists[go];
}
private static Dictionary memberLists=new Dictionary();
公共静态列表GetMemberList(此游戏对象go){
返回成员列表[go];
}

扩展方法只是“看起来”像实例方法的静态方法

然而,它们没有添加任何静态方法没有的附加功能,只是为了易于使用、维护和可读性。扩展方法也无法访问受保护/私有成员


如果
GameObject
实际上没有密封(即它没有
sealed
关键字),那么您可以编写一个继承
GameObject
的类来访问其受保护的方法/字段/属性。只有当你自己构造这些对象时,这才有效。

是的,你是对的。如果有静态方法,则该类的所有实例共享相同的数据。调用
返回成员列表是非法的。与
返回this.memberList相同
在静态方法中不可用。相反,您必须调用类:
returngameobject.memberList。但我知道你不是在寻找这个解决方案

扩展方法旨在创建额外的行为。如果您想创建额外的数据,使用继承扩展GameObject类是正确的选择

或者,您可以使用
字典
形式的字典附加成员列表。但就我个人而言,我喜欢如下所示的构图:

public class myGameObject
{
    public List<Member> memberList { get; set; }
    public GameObject go { get; set; }
}
公共类myGameObject
{
公共列表成员列表{get;set;}
公共游戏对象go{get;set;}
}

您似乎正在使用Unity3。UnityAnswers网站上有一个相关的答案可能会有所帮助:

似乎应该有办法使用内置脚本系统附加Unity框架中固有的行为。

private static ConditionalWeakTable dict=new ConditionalWeakTable();
private static ConditionalWeakTable<GameObject, List<Member>> dict = new ConditionalWeakTable<GameObject, List<Member>>();

public static List<Member> GetMemberList(this GameObject go)
{
  return dict.GetOrCreateValue(go);
}
公共静态列表GetMemberList(此游戏对象go) { 返回dict.GetOrCreateValue(go); }
ConditionalWeakTable
管理对象生存期,因为它使用弱引用。因此,如果没有其他实时引用,它不会阻止GC收集
游戏对象
,这也将允许收集
列表


它是线程安全的,但假设您希望起点是空列表(如果没有当前值,则在
GetOrCreateValue
中调用默认构造函数)。如果需要不同的起点,线程问题会变得更加复杂。

您将在
GameObject
实例上调用
GetMemberList
,它将返回该实例的列表。我想我看不出有什么问题。(扩展方法是静态的,必须在静态类型中声明,但是“extended”
这个
参数是一个实例。)如果会发生这种情况,这就是我的问题。另外,我刚刚从另一个网站上读到这篇文章,“扩展方法是一种特殊的静态方法,但是它们被调用时就像它们是扩展类型上的实例方法一样。”但是静态成员列表呢?这是一个从扩展方法访问的静态字段。@DanJ:问题是成员列表不是游戏对象的一部分。扩展方法一点也不特别,只是它们可以被视为是您要扩展的类上的方法。它们仍然是简单的旧静态方法,它们接触到的任何静态都是全局的。@Guffa啊,我误解了。我读到“我希望每个游戏对象都有自己的成员列表”,然后忽略了静态
成员列表
+1的存在,尽管我想我会提到-如果这样做,请小心,因为静态字典将保留列表中的所有项,以及GC可以访问的游戏对象实例,因此它们永远不会获得GCed。如果您使用这种方法,请确保您的
GameObject
实例正确地删除它们自己,否则您可能会遇到内存问题。这非常有趣,我现在就要尝试一下。还有@Reed Copsey,说得很好。在我找到正确的解决方案时,我会把它保存在我的文件中。还有GC问题,它会在第一次调用时抛出KeyNotFoundException,这不是线程安全的。@JonHanna:我想你的意思是,该方法不会找到你没有放在字典中的键,这是很明显的。只要将每个游戏对象的列表添加到字典中,它就不会抛出任何异常。线程安全性是一个很好的观点。