集合使用get_Keys()方法是否正确
Is it correct to use the get_Keys() method for collections
与这个问题相关:我可以在不覆盖 'keys' 成员的情况下将名为 'keys' 的键添加到哈希表吗
,我其实经常使用get_Keys()
方法作为推荐PSBase
属性 只会移动问题
换句话说,在解决方案如 的情况下,此方法对于目录键的未知列表特别方便。
该方法按预期工作(也适用于其他集合、任何 PowerShell 版本和 .Net Core):
$Hash = @{Keys = 'MyKeys'; PSBase = 'MyPSBase'}
$Hash.get_Keys()
PSBase
Keys
get_Keys()
方法显然源自:
$Hash.get_Keys
OverloadDefinitions
-------------------
System.Collections.ICollection get_Keys()
System.Collections.ICollection IDictionary.get_Keys()
关键是我找不到我在哪里找到了这个 get_Keys()
方法的引用,而且几乎没有关于这个方法的任何文档。
使用这种方法安全吗?
get_Keys()
确实是访问字典 the Keys
property 的有效(且推荐)方式,而不会冒与用户定义的键发生冲突的风险。
The method works as expected (also on other collections, any PowerShell version and .Net Core):
请注意,这仅适用于 词典([hashtable]
、[ordered]
、[SortedList]
等)- 因为它继承自 the System.Collections.IDictionary
interface.
get_Keys()
未在 public 文档中列出的原因是它 有意隐藏。
要理解为什么,我们首先需要了解.NET属性的本质
.NET 中的属性
在 .NET 中,数据类型可以有不同种类的 成员。在下面的 (C#) 示例中,我们定义了一个具有两个成员的 class,一个 field 和一个 method:
class MyClass
{
int MyField;
int MyMethod(string n = "")
{
return int.Parse(n);
}
}
这里要注意的有趣的事情是字段 就像一个变量 - 我们可以引用它来获取存储在 MyField
中的任何整数的值,并且我们可以为它分配一个(新)值。另一方面,该方法 就像一个函数 - 我们可以调用它,包括将参数值传递给它,并且它可以 return 一个值。
但是 .NET 有第三种成员类型,它有点像字段和方法之间的 混合,它看起来有点像这样(在字典的大小写):
class MyDictionary
{
string[] Keys
{
string[] _keys;
get
{
return _keys;
}
set
{
throw new InvalidOperationException("Don't mess with the keys!");
}
}
}
这被称为 属性 - 从用户的角度来看,Keys
属性 就像一个字段 - 我们可以引用它来解析它的值,我们可以(尝试)分配给它——但从实现者的角度来看,我们可以更好地控制它的行为,比如能够(有条件地)在分配时抛出异常。
现在,编译上述代码时,C# 编译器需要将 get
和 set
方法存储在 某处 以便 CLR 知道当有人试图在运行时解析 Keys
成员时执行它们。
惯例是将它们生成为常规 class 方法,通过在相关 属性 名称前加上 get_
和 set_
来命名。编译器进一步用 SpecialName
attribute 标志标记这些方法,允许编辑器和分析器将它们隐藏在用户界面和自动完成器中——这正是方法名称不会自动显示在智能感知等中的原因。
发现 属性 getters/setters
*在 PowerShell classes 中,成员总是 methods 或 properties,所以在下面我将使用此 PowerShell class 定义作为示例:
class WhosebugUser
{
[string]$Name
[int]$ID
WhosebugUser([string]$name, [int]$id)
{
$this.Name = $name
$this.ID = $ID
}
}
$Mathias = [WhosebugUser]::new("Mathias R. Jessen", 712649)
使用Get-Member
您可以使用 Get-Member -Force
:
发现与 属性 关联的自动 getters 和 setters
PS C:\> $Mathias |Get-Member ?et_* -Force
TypeName: WhosebugUser
Name MemberType Definition
---- ---------- ----------
get_ID Method int get_ID()
get_Name Method string get_Name()
set_ID Method void set_ID(int )
set_Name Method void set_Name(string )
在这里我们可以看到与$ID
和$Name
相关的getter和setter方法。
使用反射
我们也可以直接从 [type]
对象中找到这些:
PS C:\> $IDPropertyInfo = [WhosebugUser].GetProperty("ID")
PS C:\> $IDPropertyInfo.GetMethod
Name : get_ID
DeclaringType : WhosebugUser
ReflectedType : WhosebugUser
MemberType : Method
MetadataToken : 100663299
Module : RefEmit_InMemoryManifestModule
IsSecurityCritical : True
IsSecuritySafeCritical : False
IsSecurityTransparent : False
MethodHandle : System.RuntimeMethodHandle
Attributes : PrivateScope, Public, HideBySig, SpecialName
CallingConvention : Standard, HasThis
ReturnType : System.Int32
ReturnTypeCustomAttributes : Int32
ReturnParameter : Int32
IsCollectible : True
IsGenericMethod : False
IsGenericMethodDefinition : False
ContainsGenericParameters : False
MethodImplementationFlags : Managed
IsAbstract : False
IsConstructor : False
IsFinal : False
IsHideBySig : True
IsSpecialName : True
IsStatic : False
IsVirtual : False
IsAssembly : False
IsFamily : False
IsFamilyAndAssembly : False
IsFamilyOrAssembly : False
IsPrivate : False
IsPublic : True
IsConstructedGenericMethod : False
CustomAttributes : {}
注意上面的 getter 具有上面讨论的 SpecialName
属性
注意:以上输出来自 PowerShell 7,由于 reflection/type .NET Core 中的系统 API
我希望这能解释 :)
与这个问题相关:我可以在不覆盖 'keys' 成员的情况下将名为 'keys' 的键添加到哈希表吗
,我其实经常使用get_Keys()
方法作为推荐PSBase
属性 只会移动问题
换句话说,在解决方案如
该方法按预期工作(也适用于其他集合、任何 PowerShell 版本和 .Net Core):
$Hash = @{Keys = 'MyKeys'; PSBase = 'MyPSBase'}
$Hash.get_Keys()
PSBase
Keys
get_Keys()
方法显然源自:
$Hash.get_Keys
OverloadDefinitions
-------------------
System.Collections.ICollection get_Keys()
System.Collections.ICollection IDictionary.get_Keys()
关键是我找不到我在哪里找到了这个 get_Keys()
方法的引用,而且几乎没有关于这个方法的任何文档。
使用这种方法安全吗?
get_Keys()
确实是访问字典 the Keys
property 的有效(且推荐)方式,而不会冒与用户定义的键发生冲突的风险。
The method works as expected (also on other collections, any PowerShell version and .Net Core):
请注意,这仅适用于 词典([hashtable]
、[ordered]
、[SortedList]
等)- 因为它继承自 the System.Collections.IDictionary
interface.
get_Keys()
未在 public 文档中列出的原因是它 有意隐藏。
要理解为什么,我们首先需要了解.NET属性的本质
.NET 中的属性
在 .NET 中,数据类型可以有不同种类的 成员。在下面的 (C#) 示例中,我们定义了一个具有两个成员的 class,一个 field 和一个 method:
class MyClass
{
int MyField;
int MyMethod(string n = "")
{
return int.Parse(n);
}
}
这里要注意的有趣的事情是字段 就像一个变量 - 我们可以引用它来获取存储在 MyField
中的任何整数的值,并且我们可以为它分配一个(新)值。另一方面,该方法 就像一个函数 - 我们可以调用它,包括将参数值传递给它,并且它可以 return 一个值。
但是 .NET 有第三种成员类型,它有点像字段和方法之间的 混合,它看起来有点像这样(在字典的大小写):
class MyDictionary
{
string[] Keys
{
string[] _keys;
get
{
return _keys;
}
set
{
throw new InvalidOperationException("Don't mess with the keys!");
}
}
}
这被称为 属性 - 从用户的角度来看,Keys
属性 就像一个字段 - 我们可以引用它来解析它的值,我们可以(尝试)分配给它——但从实现者的角度来看,我们可以更好地控制它的行为,比如能够(有条件地)在分配时抛出异常。
现在,编译上述代码时,C# 编译器需要将 get
和 set
方法存储在 某处 以便 CLR 知道当有人试图在运行时解析 Keys
成员时执行它们。
惯例是将它们生成为常规 class 方法,通过在相关 属性 名称前加上 get_
和 set_
来命名。编译器进一步用 SpecialName
attribute 标志标记这些方法,允许编辑器和分析器将它们隐藏在用户界面和自动完成器中——这正是方法名称不会自动显示在智能感知等中的原因。
发现 属性 getters/setters
*在 PowerShell classes 中,成员总是 methods 或 properties,所以在下面我将使用此 PowerShell class 定义作为示例:
class WhosebugUser
{
[string]$Name
[int]$ID
WhosebugUser([string]$name, [int]$id)
{
$this.Name = $name
$this.ID = $ID
}
}
$Mathias = [WhosebugUser]::new("Mathias R. Jessen", 712649)
使用Get-Member
您可以使用 Get-Member -Force
:
PS C:\> $Mathias |Get-Member ?et_* -Force
TypeName: WhosebugUser
Name MemberType Definition
---- ---------- ----------
get_ID Method int get_ID()
get_Name Method string get_Name()
set_ID Method void set_ID(int )
set_Name Method void set_Name(string )
在这里我们可以看到与$ID
和$Name
相关的getter和setter方法。
使用反射
我们也可以直接从 [type]
对象中找到这些:
PS C:\> $IDPropertyInfo = [WhosebugUser].GetProperty("ID")
PS C:\> $IDPropertyInfo.GetMethod
Name : get_ID
DeclaringType : WhosebugUser
ReflectedType : WhosebugUser
MemberType : Method
MetadataToken : 100663299
Module : RefEmit_InMemoryManifestModule
IsSecurityCritical : True
IsSecuritySafeCritical : False
IsSecurityTransparent : False
MethodHandle : System.RuntimeMethodHandle
Attributes : PrivateScope, Public, HideBySig, SpecialName
CallingConvention : Standard, HasThis
ReturnType : System.Int32
ReturnTypeCustomAttributes : Int32
ReturnParameter : Int32
IsCollectible : True
IsGenericMethod : False
IsGenericMethodDefinition : False
ContainsGenericParameters : False
MethodImplementationFlags : Managed
IsAbstract : False
IsConstructor : False
IsFinal : False
IsHideBySig : True
IsSpecialName : True
IsStatic : False
IsVirtual : False
IsAssembly : False
IsFamily : False
IsFamilyAndAssembly : False
IsFamilyOrAssembly : False
IsPrivate : False
IsPublic : True
IsConstructedGenericMethod : False
CustomAttributes : {}
注意上面的 getter 具有上面讨论的 SpecialName
属性
注意:以上输出来自 PowerShell 7,由于 reflection/type .NET Core 中的系统 API
我希望这能解释 :)