开发者

What is the (undocumented?) Object.Value in .NET?

开发者 https://www.devze.com 2023-04-02 04:10 出处:网络
Where does the undocumented Object.Value come from in .NET? Is it a method or a property?What is its purpose?

Where does the undocumented Object.Value come from in .NET?

Is it a method or a property? What is its purpose?

开发者_开发知识库When I write something like (VB.NET WinForms... haven't tried C#):

TextBox1.Text = ListBox1.SelectedItem.Value

I get an error:

Option Strict On disallows late binding.

However, without Option Strict On, it seems to simply return the value of the object.

Any documentation or explanation of 'Value' in the context of the Object class?

** This question isn't about the error. That's used as an example for context. It's about what is the Value method/property of the object class? **


There is no .Value on Object.

When you turn Option Strict to Off, you allow VB.Net to dynamically invoke methods and properties. Why .Value seems to work for you isn't because Object has that property, but because the object you assigned to SelectedItem has a .Value property

Try this

Option Strict Off

Module Module1

    Public Class tst
        Public Value As Integer = 5
    End Class

    Sub Main()
        Dim a As Object
        a = New tst()
        Console.WriteLine(a.Value)
        a = New List(Of Integer)()
        Console.WriteLine(a.Value)

    End Sub

End Module

Note that the first writeline works writing out "5", but the second one throws an exception because List<> doesn't have a .Value property.


In .NET, there is no property or method named Value in Object.

The way VB.NET handles Object.Value is apparently specific to that language. In C#, for instance, the following code will not even compile:

 Object o=new Object();
 Console.WriteLine(o.Value);

with this error:

"'object' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)"

Note that this has nothing to do with late binding.

In VB.NET, on the other hand, the following code will compile without Option Strict:

 Dim o As New Object()
 Console.WriteLine(o.Value)

but will output a warning: "Late bound resolution; runtime errors could occur."

That code will indeed fail at runtime:

"Public member 'Value' on type 'Object' not found."

VB.NET allowed the code above to compile because it adds extra method calls to the method, as can be seen when we decompile the program:

object o = RuntimeHelpers.GetObjectValue(new object());
Console.Write(RuntimeHelpers.GetObjectValue(NewLateBinding.LateGet(o, null, "Value", new object[0], null, null, null)));
Console.Write(RuntimeHelpers.GetObjectValue(NewLateBinding.LateGet(o, null, "Value", new object[0], null, null, null)));

Note that LateGet supports the late binding feature of VB.NET. It checks whether the given object really does have a Value property. If it does, it gets the Value property and returns that value for Console.Write to output. Object itself doesn't have Value, but other objects do, such as System.Collections.Generic.KeyValuePair<T>.

The LateGet method of the NewLateBinding class "[e]xecutes a late-bound property get or field access call". We can dissect the arguments of LateGet like so:

o,  // Instance of the object with the property
null,  // Type (not used)
"Value", // Name of the property
new object[0], // No arguments
null,  // No argument names
null,  // No type arguments ('Value' is not generic)
null   // N/A; used only on methods with ByRef parameters

The RuntimeHelpers.GetObjectValue method boxes the given object, and is thus less relevant here.

In C#, late binding can be achieved using code like the following:

var o=new System.Collections.Generic.KeyValuePair<int,int>(0,1);
Console.WriteLine("{0}",o.GetType().GetProperty("Value").GetValue(o,new object[]{}));

I use KeyValuePair here because it contains a Value property. If it were just an Object the code will compile, but will fail at runtime with a NullReferenceException because Value doesn't exist in Object. The code gets the object's type, gets the PropertyInfo associated with the property "Value", and gets the value from the object and the PropertyInfo. LateGet most likely uses a very similar technique.


Late binding means that the method of a subclass over rides the method of a parent class. (Or, the same can be said with properties.)

In this case, I'm assuming that SelectedItem is an instance of a subclass of Object, but the reference to it that ListBox1 has is an Object instance. This means that without late binding, Object's Value property will be checked.

So, you should try casting SelectedItem to the type that it actually is.

(Disclaimer: I'm not a VB person. I'm basing this all off of the wording of the error message and my understanding of how inheritance binding typically works.)


There is no Value property on Object in .NET.

What you are seeing is dynamic object support, which lets you create new properties on anything you want without declaring them.

Your code is basically trying to do is declare a "Value" object (that is currently uninitialized) on SelectedItem (which in Windows Forms is delcared as an object). Since there is no Value property, it thinks you want to create one.

Option Strict On does not allow types to be dynamically created without being declared, so that's why you see the error. In effect, .NET is stopping you from shooting yourself in the foot, and telling you.. no... there is no Value property. And this is a prime example of why Option Strict On is such a good thing.

To illustrate my point, try changing the code to this:

ListBox1.SelectedItem.Supercalifragilisticexpialadocious

You'll get the same error. Also, read the third paragraph under Remarks in Option Strict Statement (MSDN).

0

精彩评论

暂无评论...
验证码 换一张
取 消