是否可以在不创建实例的情况下获取值?
我有这个类:
public class MyClass
{
public string Name{ get{ return "David"; } }
public MyClass()
{
}
}
现在我需要获取值为"David"的数据,但不想创建MyClass实例。
是否可以在不创建实例的情况下获取值?
我有这个类:
public class MyClass
{
public string Name{ get{ return "David"; } }
public MyClass()
{
}
}
现在我需要获取值为"David"的数据,但不想创建MyClass实例。
null
作为this
(在属性中不使用)的IL代码,使用DynamicMethod
。 示例代码:// Jon Skeet explicitly disclaims any association with this horrible code.
// THIS CODE IS FOR FUN ONLY. USING IT WILL INCUR WAILING AND GNASHING OF TEETH.
using System;
using System.Reflection.Emit;
public class MyClass
{
public string Name { get{ return "David"; } }
}
class Test
{
static void Main()
{
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var dynamicMethod = new DynamicMethod("Ugly", typeof(string),
Type.EmptyTypes);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, method);
generator.Emit(OpCodes.Ret);
var ugly = (Func<string>) dynamicMethod.CreateDelegate(
typeof(Func<string>));
Console.WriteLine(ugly());
}
}
请不要这样做。永远不要这样做。这太可怕了。它应该被践踏、切碎成小片、点燃,然后再切碎。但是,这很有趣,不是吗?;)
这段代码之所以能够工作,是因为它使用了call
而不是callvirt
。通常,即使它并没有调用虚拟成员函数,C#编译器也会使用callvirt
调用,因为这可以在IL流中“免费”进行空引用检查。与此不同的是,像这样的非虚拟调用就不会先检查是否为空,而是直接调用成员函数。如果你在属性调用中检查了this
,你会发现它是空的。
编辑:如Chris Sinclair所指出的那样,您可以使用一个开放式委托实例来更简单地实现它:
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var openDelegate = (Func<MyClass, string>) Delegate.CreateDelegate
(typeof(Func<MyClass, string>), method);
Console.WriteLine(openDelegate(null));
(但请不要这样做!)
你可以将该属性设置为 静态
public static string Name{ get{ return "David"; } }
使用方法:
MyClass.Name;
你的要求似乎有些奇怪,但我认为你在寻找某种元数据。您可以使用属性来实现此目的:
public class NameAttribute : Attribute {
public string Name { get; private set; }
public NameAttribute(string name) {
Name = name;
}
}
[Name("George")]
public class Dad {
public string Name {
get {
return NameGetter.For(this.GetType());
}
}
}
[Name("Frank")]
public class Son : Dad {
}
public static class NameGetter {
public static string For<T>() {
return For(typeof(T));
}
public static string For(Type type) {
// add error checking ...
return ((NameAttribute)type.GetCustomAttributes(typeof(NameAttribute), false)[0]).Name;
}
}
Console.WriteLine(new Dad().Name);
Console.WriteLine(new Son().Name);
Console.WriteLine(NameGetter.For<Dad>());
Console.WriteLine(NameGetter.For<Son>());
正如许多人指出的那样,您可以将属性设置为静态。
public static string Name{ get{ return "David"; } }
public class Dad
{
public static string Name { get { return "George"; }
}
public class Son : Dad
{
public static string Name { get{ return "Frank"; }
}
public static void Test()
{
Console.WriteLine(Dad.Name); // prints "George"
Console.WriteLine(Son.Name); // prints "Frank"
Dad actuallyASon = new Son();
PropertyInfo nameProp = actuallyASon.GetType().GetProperty("Name");
Console.WriteLine(nameProp.GetValue(actuallyASon, null)); // prints "Frank"
}
public const string Name = "David";
public static readonly string Name = "David";
两者的使用方式相同:
string name = MyClass.Name;
< p > const
的主要好处(和缺点)是编译代码时所有对它的引用实际上都被替换为它的值。这意味着速度会更快,但如果您改变了它的值,则需要重新编译所有引用它的代码。
public class Dad
{
public virtual string Name { get { return "George"; } }
public Dad()
{
}
}
public class Son : Dad
{
public override string Name { get{ return "Frank"; } }
public Son() : base()
{
}
}
它可以被静态覆盖吗? - user1475694public static class Extensions {
public static bool IsNullOrEmpty(this string obj) {
return obj != null && obj.Length > 0;
}
}
...
string s = null;
bool empty = s.IsNullOrEmpty(); // Fine
即使使用不具有相同规则的语言的属性也可以正常工作。例如C++/CLI:
#include "stdafx.h"
using namespace System;
using namespace ClassLibrary1; // Add reference
int main(array<System::String ^> ^args)
{
MyClass^ obj = nullptr;
String^ name = obj->Name; // Fine
Console::WriteLine(name);
return 0;
}
public class MyClass
{
public static string Name { get { return "David"; } }
public MyClass()
{
}
}
像这样获取:
string name1 = MyClass.Name;
这是不可能的。由于Name
是一个实例属性,只有当你有一个实例时才能获取它的值。
此外,请注意你所谈论的不是一个参数,而是一个属性。