如何使用VB.NET为字符串赋值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10371712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to assign value to string using VB.NET?
提问by Pan Pizza
Consider following code:
考虑以下代码:
Dim S1 As String = "a"
'this is the string in a file
Dim StringFromFile As String = "S1=hello"
Dim temp() As String = Split(StringFromFile, "=", -1, CompareMethod.Binary)
'temp(0) = variable name
'temp(1) = variable value
'my question is: how to assign value to S1?
I have declared a string named S1. Now I want to assign new value to S1. The new string value is stored in a file using following format: [variable name][= as separator][string value]. How do I assign the value to S1 after retrieving the string variable name and value that stored in a file?
我已经声明了一个名为 S1 的字符串。现在我想为 S1 分配新值。新的字符串值使用以下格式存储在文件中:[variable name][= as separator][string value]。检索存储在文件中的字符串变量名称和值后,如何将值分配给 S1?
NOTE:
笔记:
temp(0) = "S1"
temp(1) = "hello"
It should be noted that the string with the data comes from a file that may change from time to time! When the file changes, I want the variables to change as well.
需要注意的是,带有数据的字符串来自一个可能会不时变化的文件!当文件更改时,我希望变量也更改。
Further clarification
进一步澄清
I need a piece of code that when processing a string like this "S1=hello", the code will first find a declared variable (i.e. S1), and then assign the S1 variable with "hello" string. The "=" just acted as separator for variable name and variable value.
我需要一段代码,在处理像“S1=hello”这样的字符串时,代码会首先找到一个声明的变量(即S1),然后将“hello”字符串分配给S1变量。“=”只是作为变量名和变量值的分隔符。
UPDATE:
更新:
My attempt to use Mathias Lykkegaard Lorenzen's EDIT 2 example but failed with "NullReferenceException" on this line "Field.SetValue(Me, VariableValue)". Please help me fix the problem. Following is my code based on Mathias Lykkegaard Lorenzen's EDIT 2 example:
我尝试使用 Mathias Lykkegaard Lorenzen 的 EDIT 2 示例,但在这一行中以“NullReferenceException”失败"Field.SetValue(Me, VariableValue)"。请帮我解决问题。以下是我基于 Mathias Lykkegaard Lorenzen 的 EDIT 2 示例的代码:
Public Sub Ask()
Try
Dim S1 As String = "a"
Dim StringFromFile As String = "S1=hello"
Dim temp() As String = Split(StringFromFile, "=", -1, CompareMethod.Binary)
'temp(0) = variable name
'temp(1) = variable value
'my question is: how to assign value to S1?
Dim TypeOfMe As Type = Me.GetType()
'did this for readability.
Dim VariableName As String = temp(0)
Dim VariableValue As String = temp(1)
'get the field in the class which is private, given the specific name (VariableName).
Dim Field As FieldInfo = TypeOfMe.GetField(VariableName, BindingFlags.NonPublic Or BindingFlags.Instance)
'set the value of that field, on the object "Me".
Field.SetValue(Me, VariableValue) '<-- this line caused NullReferenceException
MessageBox.Show(S1)
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
采纳答案by Teen
You can use reflectionto set S1 value:
您可以使用反射来设置 S1 值:
Imports System.Reflection
Public Class Form1
Public S1 As String = "a"
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim StringFromFile As String = "S1=hello"
Dim temp() As String = Split(StringFromFile, "=", -1, CompareMethod.Binary)
'temp(0) = variable name
'temp(1) = variable value
SetS1(Me, "S1", temp(1))
MessageBox.Show(S1)
End Sub
''' <summary>
'''
''' </summary>
''' <param name="obj">the class that stores your S1 public field</param>
''' <param name="fieldName">that is your S1 field</param>
''' <param name="Value">S1 new value, that is hello</param>
''' <remarks></remarks>
Public Sub SetS1(ByVal obj As Object, ByVal fieldName As String, ByVal Value As Object)
Try
Dim fi As FieldInfo = obj.GetType().GetField(fieldName, BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
If Not fi Is Nothing Then
fi.SetValue(obj, Value)
End If
Catch ex As Exception
End Try
End Sub
End Class
Additional resource
附加资源
有一本关于反射的书很好,看看:Visual Basic .NET Reflection Handbook
Reflection is a mechanism provided by .NET that enables developers to make their programs more flexible and dynamic. Reflection makes it possible for applications to be more modular, extensible, and configurable. Building on the basics of object-orientation and the .NET type system, reflection provides mechanisms for dynamically examining, modifying, and even creating objects at run time. .NET also adds the ability for programmers to add attributes to their types, which provide metadata about the type which can be examined and used through reflection at runtime.
This book examines all the ways reflection can be used, and identifies practical applications and important programming techniques that rely upon reflection for their functionality. It covers the reflection API, the use of attributes in .NET, and also looks at the mechanisms .NET provides for dynamic generation of code - all techniques that allow developers to build more flexible, dynamic applications.
反射是 .NET 提供的一种机制,它使开发人员能够使他们的程序更加灵活和动态。反射使应用程序变得更加模块化、可扩展和可配置。基于面向对象和 .NET 类型系统的基础,反射提供了在运行时动态检查、修改甚至创建对象的机制。.NET 还增加了程序员为他们的类型添加属性的能力,这些属性提供了有关类型的元数据,可以在运行时通过反射进行检查和使用。
本书探讨了可以使用反射的所有方式,并确定了依赖反射来实现其功能的实际应用程序和重要的编程技术。它涵盖了反射 API、在 .NET 中使用属性,还研究了 .NET 为动态生成代码提供的机制 - 所有技术都允许开发人员构建更灵活的动态应用程序。
回答by Heinzi
If I understood your question correctly, you want to assign the value of temp(1)to the local variable with the same name as the value of temp(0). So, if your file contains S1=hello, S2=world, you want your code to assign "hello" to variable S1(and "world" to variable S2, if such a variable exists).
如果我理解正确你的问题,你想要的值赋给temp(1)具有相同的名称的值局部变量temp(0)。因此,如果您的文件包含S1=hello, S2=world,您希望您的代码将“hello”分配给变量S1(S2如果存在这样的变量,则将“world”分配给变量)。
Unfortunately, Visual Basic does not support assigning values to local variables whose names are determined at run-time. If S1were a class field or property, you could assign it using reflectionor a serialization library (e.g. XmlSerializer, which however expects input files to be in XML format rather than name=value pairs).
不幸的是,Visual Basic 不支持为名称在运行时确定的局部变量赋值。如果S1是类字段或属性,您可以使用反射或序列化库(例如XmlSerializer,但它期望输入文件采用 XML 格式而不是名称=值对)来分配它。
In general, a bit more context would be needed to suggest the best alternative for your situation. For example, if you just have names S1, ..., S20, I'd use an array. If your keys are arbitrary names, a Dictionarymight be more appropriate.
一般来说,需要更多的上下文来建议适合您情况的最佳替代方案。例如,如果您只有 names S1, ..., S20,我会使用array。如果您的键是任意名称,则字典可能更合适。
回答by Mathias Lykkegaard Lorenzen
I hope I am getting the question right. It seems to me as if you want to assign the value of temp(1)to the variable S1which you have declared earlier.
我希望我的问题是正确的。在我看来,好像您想将 的值分配给您之前声明temp(1)的变量S1。
This is done using a simple operation:
这是通过一个简单的操作完成的:
S1 = temp(1)
Or if that is not clear for you, Setcan be used as well:
或者,如果您不清楚,Set也可以使用:
Set S1 = temp(1)
More information on that hereand here.
Edit 1
编辑 1
Reflecting on what you just wrote as a comment to your question, the string that you are splitting comes from a file which may change at any given point in time.
回想一下您刚刚作为对问题的评论所写的内容,您正在拆分的字符串来自一个文件,该文件可能会在任何给定时间点发生更改。
For that, I would consider using either a database (with triggers), or a FileSystemWatcher(documentation here) object to monitor a specific directory for file changes.
为此,我会考虑使用数据库(带触发器)或FileSystemWatcher(此处的文档)对象来监视特定目录的文件更改。
A sample solution using this is shown below.
使用它的示例解决方案如下所示。
Dim watcher As New System.IO.FileSystemWatcher()
watcher.Path = "C:\MyPathToMonitor"
watcher.Filter = "*MyFileNameToLookFor" 'could be *MyFile.txt
'assign the event. could be done by declaring the watcher `WithEvents` in the class scope too.
AddHandler watcher.Changed, AddressOf OnChanged
And then, in your event handler:
然后,在您的事件处理程序中:
Private Shared Sub OnChanged(source As Object, e As FileSystemEventArgs)
'here we just say that StringFromFile has been assigned to the file contents now.
Dim temp() As String = Split(StringFromFile, "=", -1, CompareMethod.Binary)
'remember to have the S1 variable in your class scope.
S1 = temp(1)
End Sub
Edit 2
编辑 2
If you want to be able to change the value of a variable given the name of that variable as a string, then you should look into Reflection, which allows you to evaluate code at runtime, as opposed to compile-time.
如果您希望能够更改给定变量名称的变量值 a string,那么您应该查看反射,它允许您在运行时评估代码,而不是编译时。
I gave you a sample code below which pretty much sums up the use of Reflection.
我在下面给了你一个示例代码,它几乎总结了反射的使用。
'get the reflection type of the current class.
Dim TypeOfMe As Type = Me.GetType()
'did this for readability.
Dim VariableName = temp(0)
Dim VariableValue = temp(1)
'get the field in the class which is private, given the specific name (VariableName).
Dim Field As FieldInfo = TypeOfMe.GetField(VariableName, BindingFlags.NonPublic Or BindingFlags.Instance)
'set the value of that field, on the object "Me".
Field.SetValue(Me, VariableValue)
回答by pms1969
You can't reflect out a local variable because after compilation, the compiler loses the names of locals, but maintains names for those at class level.
您无法反映局部变量,因为编译后,编译器会丢失局部变量的名称,但会保留类级别的名称。
So to make your example work, you need to make S1 a class level variable, not have it as an internal variable to the method.
因此,为了使您的示例工作,您需要将 S1 设为类级别变量,而不是将其作为方法的内部变量。
Public Class Class1
Dim S1 As String = "a"
Public Sub Ask()
Try
Dim StringFromFile As String = "S1=hello"
Dim temp() As String = Split(StringFromFile, "=", - 1, CompareMethod.Binary)
'temp(0) = variable name
'temp(1) = variable value
'my question is: how to assign value to S1?
Dim TypeOfMe As Type = Me.GetType()
'did this for readability.
Dim VariableName As String = temp(0)
Dim VariableValue As String = temp(1)
'get the field in the class which is private, given the specific name (VariableName).
Dim Field As FieldInfo = TypeOfMe.GetField(VariableName, BindingFlags.NonPublic Or BindingFlags.Instance)
'set the value of that field, on the object "Me".
Field.SetValue(Me, VariableValue) '<-- this line caused NullReferenceException (no more.)
Console.WriteLine("S1 using reflection")
Console.WriteLine(S1)
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
End Class
However, as has already been said here, a much more pragmatic approach is to use a dictionary.
然而,正如这里已经说过的,更实用的方法是使用字典。
Public Class Class2
Public Sub Ask()
Try
Dim StringFromFile As String = "S1=hello"
Dim temp() As String = Split(StringFromFile, "=", - 1, CompareMethod.Binary)
' the way you probably should do it.
Dim test As Dictionary(Of string, string) = New Dictionary(Of String,String)()
test.Add(temp(0), temp(1))
Console.WriteLine("S1 using dictionary")
Console.WriteLine(test("S1"))
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
End Class
if you had a dictionary that already had the values you were after in it, you wouldn't be doing an add of course, you would just be setting the key to the new value like test(temp(0)) = temp(1)
如果您的字典中已经包含您想要的值,那么您当然不会进行添加,您只需将键设置为新值,例如 test(temp(0)) = temp(1)
What you have to remember is that Reflection is expensive. Don't do it unless you absolutely have to.In this instance, I can't see the real need for it, and I've seen nothing to convince me you have no other choice. Try and keep your solution as simple as possible.
你必须记住的是,反射是昂贵的。 除非万不得已,否则不要这样做。在这种情况下,我看不到它的真正需要,而且我没有看到任何东西可以说服我您别无选择。尝试使您的解决方案尽可能简单。
回答by Pradeep Kumar
While you can get access to the Local Variables of a method using the LocalVariablesProperty of the Reflection.MethodBodyclass, there is no good way to set the values, because the variable names are not stored anywhere. So you can't lookup via reflection by variable names. You can enumerate the local variables by their index/type, but there is no definitive way to tell which variable is which one, except that you know beforehand the exact sequence in which they are declared (in which case you can go by index).
虽然您可以使用类的LocalVariables属性访问方法的局部变量Reflection.MethodBody,但没有设置值的好方法,因为变量名称没有存储在任何地方。所以你不能通过变量名通过反射进行查找。您可以通过它们的索引/类型枚举局部变量,但没有确定的方法来确定哪个变量是哪个变量,除非您事先知道它们声明的确切顺序(在这种情况下您可以通过索引)。
You can find more information about what I'm saying in the msdn topic here:
您可以在此处的 msdn 主题中找到有关我所说内容的更多信息:
MethodBody.LocalVariables Property
If you are anyways needing to lookup local variables via reflection, then it is an utterly bad design and you should work more on that part (refactoring your code). You should avoid using reflection altogether wherever possible, because it has large overheads and is extremely slow. The Dictionary/SortedDictionary approach is a much better way to go in the situation you are in.
如果您无论如何都需要通过反射查找局部变量,那么这是一个非常糟糕的设计,您应该在这部分上做更多的工作(重构您的代码)。你应该尽可能避免完全使用反射,因为它有很大的开销并且非常慢。Dictionary/SortedDictionary 方法是处理您所处情况的更好方法。
回答by Mike Calvert
If you add your variables to a keyed dictionary of variables, you can use set to set the value of the value in the Key Value pair. Check this out:
如果将变量添加到变量的键控字典中,则可以使用 set 来设置键值对中的值。看一下这个:
Dim dctHolder As New Dictionary(Of String, Object)
Dim S1 As String
Dim tmp() As String = {"S1","Split Up Value"}
dctHolder.Add("S1",S1)
Set dctHolder(tmp(0)) = tmp(1)
回答by svick
If you only want to assign the value of temp(1)to S1, you can do that:
如果你只想要分配的价值temp(1)来S1,你可以这样做:
S1 = temp(1)
If you have a small, fixed set of possible values, you could try to use Select Case:
如果您有一组小的、固定的可能值,您可以尝试使用Select Case:
Select Case temp(0)
Case "S1"
S1 = temp(1)
Case "S2"
S2 = temp(1)
End Select
But generally, the best way to do this is to use a dictionary to hold the values, not variables:
但一般来说,最好的方法是使用字典来保存值,而不是变量:
Dim dict = New Dictionary(Of String, String)
dict(temp(0)) = temp(1)
You can then get the value of S1by something like:
然后,您可以通过以下方式获取值S1:
dict("S1")

