问题
I've used VB.net for several years now, but keep coming across little quirks that I don't know how to work around. Curiosity finally got the best of me, so I ask now: is there a way to create an object without assigning it?
For example, say I have an Engine class, that I want to instantiate and have it immediately do whatever it needs to do. If there's nothing I need to do with Engine after creating it, I have, till now, done something like:
dim myEngine as new Engine()
Is there a way to avoid the "dim myEngine as" part? You certainly can in Java. I could just create an object with "new Engine()" in java and not assign it to anything.
Why do I need this? Because often I want to create a delegate object (hence I called it "engine") that performs some functionality, but otherwise I don't need to ever reference it. I used to have such objects have a "public sub perform", but have found that cumbersome -- I'd rather just create the object and not worry about remembering to call its perform method. And I find it aesthetically displeasing to create references to objects that I don't intend to use.
Any VB guru have a suggestion?
Thanks,
-- Michael
回答1:
To do this you need to put the New declaration inside Parentheses ( )
you can try this syntax:
Call New TheClass().Method1()
or:
DoSomething(New TheClass())
or even:
DoSomething(New TheClass().GetStringData())
Source: http://tutorials.beginners.co.uk/vb-net-programming-part-6-interacting-with-objects.htm
回答2:
Perhaps the issue is your design choice of the constructor performing real work, instead of putting that real work in methods? The constructor is meant to build the object's state from one or more set of parameters. Methods perform actions.
A static class can indeed have its own private methods and fields. Not instances of them, sure, but for a single "instance" that would work fine.
Could you go into a bit more detail about the whys of this design choice/methodology, and perhaps we can offer some insight in how to design your objects more effectively.
Alternatively, you can anonymously create an object and call a method by:
Call New obj().method()
回答3:
Thanks for your answers, everybody. It seems like few of you agree with my particular design choice, which is fine, and I'd love to hear how you would go about this problem. But first let me explain why I'm doing what I'm doing.
Suppose I have a class, Exporter, dedicated to exporting a file. It is a class, not a module, because I might want to have several exporters each with their own settings, etc. So now I have
dim myExporter as new Exporter()
My exporter needs to have some data given to it, and a filename to save into. So I now have several options:
1) keep the empty exporter constructor and add myExporter.performExport(data, filename)
I don't particularly like this, if the exporter is complicated (and my premise is that it is -- otherwise a module would have done fine), then I want it to maintain its own state, which just might be related to the data and filename. It makes more sense to redo the constructor, as in option #2:
2) pass the parameters in the constructor:
dim myExporter as new Exporter(data, filename)
and then call with a simple no-argument call: myExporter.performExport()
This is fine, but notice how essentially, even though I'm declaring myExporter, I am only using it as a one-shot call: create and perform export. Essentially I don't need a reference to it, as @brian-m suggested, I could just do
Call new Exporter(data, filename).performExport()
(@code-gray, note how I now am using an object without a reference, yet it's not non-sensical).
But now I just have to type extra code every time -- the performExport() part. If I know I will always want to act upon the object as soon as it's created (@brian-m, I agree that there are some cases when I might want to prepare my object and then DELAY execution, but at other times the execution may as well happen immediately after object creation) I may as well put the acting code in the constructor too, so I don't worry about forgetting to make the call. So now I have
dim myExporter as new Exporter(data, filename)
which needs no further call, because it exports immediately upon being created. From the rest of the program's perspective, I don't care what happens to the exporter once it's done -- I did not mean to get hung up on garbage collection, I just wanted to say that I have no need in maintaining a reference to the exporter.
So far so good? If so, then I hope you'll agree with me that it would make even more sense to get rid of the "dim myExporter as" part, and just leave "new Exporter(data, filename)". Except VB.NET, unlike Java, does not seem to allow that.
Thanks for reading, I'm looking forward to hearing your suggestions.
-- Michael
回答4:
Maybe you can declare your global object in a Module...
Module GlobalModule
Public x As Double = 110
Public myObject As AutonomousObject = New AutonomousObject() ' This will instantiate the object
End Module
... create a Class ...
Public Class AutonomousObject
Public Sub New()
MessageBox.Show("Hello, I was instantiated now. " + System.Reflection.MethodBase.GetCurrentMethod().Name)
End Sub
Public Sub Start()
MessageBox.Show("Hello, I am initialized! " + System.Reflection.MethodBase.GetCurrentMethod().Name)
End Sub
End Class
... and then use it from anywhere, without need to instantiate it again
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
MessageBox.Show(GlobalModule.x) ' Will display 110
' OR
GlobalModule.myObject.Start() ' This will call a method that will display a message
End Sub
回答5:
There are times when an object's constructor will "connect" the object to another object passed as a parameter, and the code which calls the constructor will have no further use for the object reference. I would suggest that "New" calls which ignore the result should not be used outside the class, but instead the class should provide a wrapper method something like:
Sub AddNewItemToList(TheList as MyListType, TheData as DataToGoInNewItem)
GC.KeepAlive(New MyListNode(TheList, TheData))
End Sub
The GC.KeepAlive method could really be called "GC.PretendToUseTheParameterButDontActuallyDoAnythingWithIt", which would be precisely the semantics you're looking for here.
回答6:
If i understand this correctly then you are trying to avoid the memory that would be used up by the object that you are instantiating even when you don't want to use it. If that's the case then why not use Singleton Object. Which is instantiated only once and first time when you call it.
回答7:
You can have a dummy method on your class and use the aforementioned solution with the Call keyword
Call (New Engine()).dummy()
To spice things up you can probably create a dummy extension method on any of your existing classes
Or you can use reflection to one line the code without modifying anything
GetType(Engine).GetConstructor(types:= New Type(){} ).Invoke(parameters:= New Object(){})
Btw, you can add me to the list of people not agreeing with your design choice of doing significant work in the constructor.
来源:https://stackoverflow.com/questions/4964424/constructing-an-object-without-assigning-it-in-visual-basic-net