简体   繁体   English

C#获取属性值而不创建实例?

[英]C# Get property value without creating instance?

Is it possible to get value without creating an instance ? 是否可以在不创建实例的情况下获得价值?

I have this class: 我有这个课:

public class MyClass
{
    public string Name{ get{ return "David"; } }

    public MyClass()
    {
    }
}

Now I need get the value "David", without creating instance of MyClass. 现在,我需要获取值“ David”,而无需创建MyClass实例。

Real answer : no. 真实答案 :不可以。 It's an instance property, so you can only call it on an instance. 这是一个实例属性,因此您只能在实例上调用它。 You should either create an instance, or make the property static as shown in other answers. 您应该创建一个实例,或者使该属性为静态,如其他答案所示。

See MSDN for more information about the difference between static and instance members. 有关静态成员和实例成员之间的区别的更多信息,请参见MSDN

Tongue-in-cheek but still correct answer : 在舌头上,但仍然是正确的答案

Is it possible to get value without creating an instance ? 是否可以在不创建实例的情况下获得价值?

Yes, but only via some really horrible code which creates some IL passing in null as this (which you don't use in your property), using a DynamicMethod . 是的,但是只能通过一些非常可怕的代码来创建一些IL,它使用DynamicMethod this null传递为null (您不会在属性中使用)。 Sample code: 样例代码:

// 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());
    }
}

Please don't do this. 请不要这样做。 Ever. 曾经 It's ghastly. 真可怕 It should be trampled on, cut up into little bits, set on fire, then cut up again. 应该踩踏它,切成小块,放火燃烧,然后再切成小块。 Fun though, isn't it? 不过很有趣,不是吗? ;) ;)

This works because it's using call instead of callvirt . 之所以有效,是因为它使用的是call而不是callvirt Normally the C# compiler would use a callvirt call even if it's not calling a virtual member because that gets null reference checking "for free" (as far as the IL stream is concerned). 通常,C#编译器将使用callvirt调用, 即使它没有调用虚拟成员,因为它会“免费”获取空引用(就IL流而言)。 A non-virtual call like this doesn't check for nullity first, it just invokes the member. 像这样的非虚拟调用不会先检查无效性,它只会调用成员。 If you checked this within the property call, you'd find it's null. 如果您在属性调用中选中了this ,则会发现它为null。

EDIT: As noted by Chris Sinclair, you can do it more simply using an open delegate instance: 编辑:正如克里斯·辛克莱尔(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));

(But again, please don't!) (但是再次,请不要!)

You can make that property static 您可以将该属性设为静态

public static string Name{ get{ return "David"; } } 

Usage: 用法:

MyClass.Name;

You can make your property static , as pointed out by many others. 正如其他许多人指出的那样,您可以将您的属性设为静态

public static string Name{ get{ return "David"; } }

Be aware that this means your instances of MyClass will no longer have their own Name property, since static members belong to the class, not the individual object instances of it. 请注意,这意味着MyClass实例将不再具有其自己的Name属性,因为静态成员属于该类,而不是该类的单个对象实例。

Edit: In a note, you mentioned that you want to override the Name property in subclasses. 编辑:在注释中,您提到要覆盖子类中的Name属性。 At the same time, you want to be able to access it at the class level (access it without creating an instance of your class). 同时,您希望能够在类级别进行访问(无需创建类实例即可访问它)。

For the static properties, you would simply create a new Name property in each class. 对于静态属性,您只需在每个类中创建一个新的Name属性。 Since they are static , you're always (almost always, yay reflection) going to access them using a specific class, so you'd be specifying which version of Name you want to get. 由于它们是static ,因此您总是(几乎总是,使用反射)将使用特定的类来访问它们,因此,您将指定要获取的Name版本。 If you want to try and hack polymorphism in there and get the name from any given subclass of MyClass, you could do so using reflection, but I wouldn't recommend doing so. 如果您想在那里尝试破解多态性并从MyClass的任何给定子类中获取名称,则可以使用反射来实现,但我不建议这样做。

Using the example from your comment: 使用您评论中的示例:

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"
}

As a side note, since you are declaring a property that has only a getter and it is returning a constant value, I recommend possibly using a const or static readonly variable instead. 附带说明一下,由于您声明的属性只有一个getter且返回的是常量,因此建议您改用 const或static readonly变量。

 
 
 
 
  
  
  public const string Name = "David"; public static readonly string Name = "David";
 
 
  

Usage for both would be the same: 两者的用法将相同:

 
 
 
 
  
  
  string name = MyClass.Name;
 
 
  

The main benefit (and drawback) of const is that all references to it are actually replaced by its value when the code is compiled. const的主要优点(和缺点)是,在编译代码时,对它的所有引用实际上都被其值替换。 That means it will be a little faster, but if you ever change its value, you will need to recompile ALL code that references it. 这意味着它会更快一些,但是如果您更改它的值,则需要重新编译所有引用它的代码。

You requirements do seem strange, but I think you're looking for some kind of metadata. 您的要求确实有些奇怪,但是我认为您正在寻找某种元数据。 You can use an attribute to achieve this: 您可以使用属性来实现此目的:

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;
  }
}

Now this code can get names with and without instances: 现在,此代码可以获取带有和不带有实例的名称:

Console.WriteLine(new Dad().Name);
Console.WriteLine(new Son().Name);
Console.WriteLine(NameGetter.For<Dad>());
Console.WriteLine(NameGetter.For<Son>());

Whenever you write C# code, always check if your method and property getter/setter code does anything at all with other instance members of the class. 每当您编写C#代码时,请始终检查您的方法和属性getter / setter代码是否与该类的其他实例成员一起执行任何操作 If they don't, be sure to apply the static keyword. 如果没有,请确保应用static关键字。 Certainly the case here, it trivially solves your problem. 当然是这种情况,它可以轻松解决您的问题。

The reason I really post to this question is that there's a bit of language bias at work in some of the answers. 我之所以真正提出这个问题,是因为某些答案在工作中存在语言偏见。 The C# rule that you can't call an instance method on a null object is a specific C# language rule. 您不能在空对象上调用实例方法的C#规则是特定的C#语言规则。 It is without a doubt a very wise one, it really helps to troubleshoot NullReferenceExceptions, they are raised at the call site instead of somewhere inside of a method where it gets very hard to diagnose that the this reference is null. 毫无疑问,这是一个非常明智的选择,它确实有助于对NullReferenceExceptions进行故障排除,它们是在调用站点引发的,而不是在很难诊断引用为null的方法内部的某个位置引发的。

But this is certainly not a requirement to the CLR, nor of every language that run on the CLR. 但这当然不是CLR的要求,也不是CLR上运行的每种语言的要求。 In fact, even C# doesn't enforce it consistently, you can readily bypass it in an extension method: 实际上,即使C#也不能始终如一地实施它,您可以在扩展方法中随时跳过它:

public static class Extensions {
    public static bool IsNullOrEmpty(this string obj) {
        return obj != null && obj.Length > 0;
    }
}
...
        string s = null;
        bool empty = s.IsNullOrEmpty();    // Fine

And using your property from a language that doesn't have the same rule works fine as well. 而且,使用没有相同规则的语言来使用您的媒体资源也可以正常工作。 Like C++/CLI: 像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;
}

Create a static property: 创建一个静态属性:

public class MyClass
{
    public static string Name { get { return "David"; } }

    public MyClass()
    {
    }
}

Get it like so: 像这样得到它:

string name1 = MyClass.Name;

创建一个静态类或静态属性,而不必显式实例化它。

That is not possible. 这是不可能的。 As Name is an instance property, you can only get its value if you have an instance. 由于Name是实例属性,因此只有拥有实例时才能获取其值。

Also, note that you are not talking about a parameter , but about a property . 另外,请注意,您并不是在谈论参数 ,而是在谈论属性

暂无
暂无

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

相关问题 在不创建C#6.0的情况下访问私有属性值 - Accessing Private Property value in C# 6.0 without creating it c#从类的实例中获取静态属性的值 - c# Get value of static property from the instance of a class 创建一个属性来存储实例C# - creating a property to store an instance c# 在c#中,是否有可能在不知道包含类的情况下从该属性的实例中获取附加到该属性的属性? - Is it possible in c# to get the attributes attached to a property from within the instance of that property, without knowing the containing class? 创建没有0值的C#Enum实例 - Creating an instance of an C# Enum with no 0 value C#nameof运算符引用实例属性可以没有实例吗? - Can C# nameof operator reference instance property without instance? C#-是否可以在不为值创建私有var的情况下用额外的操作定义属性的“ set”方法? - C# - Can I define a property's “set” method with extra actions without creating a private var for the value? 是否可以在不创建对象实例的情况下获取对象属性名称字符串? - Is it possible to get an object property name string without creating the object instance? C# 为什么我可以通过属性访问非 static 类的方法和属性,而无需先创建该 class 的实例? - C# Why can I access a non static class' methods and properties via a property, without creating an instance of that class first? 使用反射在 C# 中创建没有默认构造函数的类型实例 - Creating instance of type without default constructor in C# using reflection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM