Open WolvenRA opened 4 years ago
@zspitz
Properties defined in the method body. Just like local functions (That Microsoft VB doesn't have either, but C# does).
@zspitz A VB.NET equivalent of this
which is a better solution to
That's all well and good until some other member within the class calls the field directly instead of the property. And I don't think there's any way to prevent that kind of access.
@tverweij I don't think C# has local properties, only local methods.
@Happypig375 : That is what I meant to say.
@zspitz
Wouldn't it be nice if things would just auto-initialize to the non-null defaults, unless we specified otherwise?
What's the non-nullable default for
System.Random
? OrSqlConnection
? We can get close enough for government work by saying "This variable must be initialized right away, and assigningNothing
-- or something that might beNothing
-- to it is not allowed".
When the object is created, unless overridden, all fields and properties would be set to whatever the base type default value is. 0 for Integers, Floats, Decimals, etc. An empty string for String, a blank for Char. So for SqlConnection the Connection String value would be a blank string, the Connection Timeout would be 0, etc..
Gettting a Null Reference Exception because we try to access an object that hasn't been Created yet makes sense (actually the error should be "'Object' doesn't exist"). But other than that, I shouldn't ever have to worry about some value being Null. Unless I SPECIFICALLY defined something as Nullable... which I would never do.
@WolvenRA Ahh yes, a Person
with name
and age 0 is definitely a valid object.
Or a table with color 0x00000000 (transparent) and 0 legs.
@WolvenRA
When the object is created, unless overridden, all fields and properties would be set to whatever the base type default value is.
What about fields whose type is not a value type? The default value for these is generally Nothing
.
@Happypig375
Ahh yes, a Person with name and age 0 is definitely a valid object.
Isn't it generally more appropriate to store the date of birth in the object and have age calculated from the date of birth? Assuming Date
defaults to Date.MinValue
, the default person would be really, really old. 😊
@WolvenRA post is the one that makes more sense in this whole thread. And yes a person with no name and 0 age is a perfectly acceptable object in a neonatal ICU, or as far as the programmer instantiate a person without initialising its properties. That's a mistake of the programmer and as such shall remain. For all other objects without a default value, Nothing is a perfectly acceptable value.
Dim ToSeeHere as Object = Nothing 'move along.
@Padanian Consider the following code:
Dim ToSeeHere As Object = Nothing
Console.WriteLine(ToSeeHere.GetType.Name) ' falls with a NullReferenceException
Where was the programmer's mistake? Was the mistake in originally assigning Nothing
, and that should have been prevented? Or was the mistake in trying to access something that might have had Nothing
without checking that ToSeeHere IsNot Nothing
first? We don't know the author's original intention when declaring ToSeeHere
.
Now, if there's some way to separate between the two (either explicitly declaring the null-allowed, or explicitly declaring the null-disallowed), the compiler can warn either on the inappropriate assignment ("You're trying to assign Nothing
to something which isn't supposed to take Nothing
) or on the potentially unsafe usage ("You're trying to use a property or method of something that might be Nothing
").
Just as the compiler prevents the mistake of trying to add two instances of System.Random
, because Operator '+' is not defined for types 'Random' and 'Random'., if the compiler can warn about Dereference of a possibly null reference. it should certainly do so.
Objects needs to be declared, instantiated and then initialised. Anything declared, instantiated but not initialised OR purposefully initialised to Nothing have value Nothing. That's all there is about this matter. Oh no, there is a thing: the exception message is wrong. It shall read NothingReferenceException.
@Padanian The error message comes from the CLR; Nothing
is used by VB to represent the concept of a reference that doesn't point to anything.
Anything declared, instantiated but not initialised OR purposefully initialised to Nothing have value Nothing.
Except that somewhere in the intervening code you changed the Nothing
-ed variable it to another object. Or you changed a previously initialized variable to Nothing
. Or your code usually intializes the variable, except on alternate Tuesdays, when it gets set to Nothing
. Or your JSON result returns Nothing
when you expect it to return something. And I've forgotten that this previously non-Nothing
variable was set to Nothing
and try to call a property or method on a non-existent object.
Variables can vary; that's why they're called variables.
My point is, with null reference type handling, the compiler can identify and warn about such potential problems, making it easier to fix them.
@zspitz
@Padanian Consider the following code:
Dim ToSeeHere As Object = Nothing Console.WriteLine(ToSeeHere.GetType.Name) ' falls with a NullReferenceException
Where was the programmer's mistake? Was the mistake in originally assigning
Nothing
>
I would argue that IF the programmer assigned Nothing then, yes, it's their responsibility to check for that (and having the compiler give a Warning is fine). But if the programmer did this:
Dim ToSeeHere As New Object
Then ANY and ALL properties, fields, etc. SHOULD be set to either some predetermined value OR to the base default value for that property\field type... NOT NOTHING!
If they did this:
Dim ToSeeHere As Object
Then it's up to them to instantiate it before they try to use it (and again having the compiler give a Warning is fine).
And @Happypig375
Ahh yes, a Person with name and age 0 is definitely a valid object. Or a table with color 0x00000000 (transparent) and 0 legs.
Whether it's valid or not is irrelevant. That's the programmers responsibility. BUT, it SHOULDN'T be Null\Nothing, (unless the programmer SPECIFICALLY set it to Null\Nothing).
Other than an un-instantiated object, NOTHING should be Nothing or Null... :) (Again, unless the programmer SPECIFICALLY set it to that.)
I forget who the guy was that originally came up with the idea of Null (originally as a string terminator I believe), but I read an article where HE said it was the biggest mistake in the history of computer science. I agree with him. Nulls are just *&^%$ stupid.
@WolvenRA
Class A
Public O As Object ' Uninitialised, so Nothing
End Class
Class B
Public A As A ' Uninitialised, so Nothing
End Class
Dim A1 As A ' Nothing
Dim A2 As New A ' Now A2.A.O is initialised?
And this:
Public Class C
Public A As Console ' Yes, System.Console
End Class
Dim c As New C ' What is the value of c.A?
@zspitz
Dim ToSeeHere As New Object
Dim ToSeeHere As Object = New Object Console.WriteLine(ToSeeHere.GetType.Name)
In fact correctly returns
Object
I think the whole discussion here is about good programming practice.
There are times where objects have default properties set, like e.g. System.IO.Ports.SerialPort , but can be instantiated and uninstatiated at runtime.
Trying to open or close a SerialPort that hasn't been instantiated, or that in the meantime has been disposed of or the underlying hardware removed, eg. a disconnected USB port, will cause a NullReferenceException.
In the above specific case, an object with default values, related to a no longer underlying hw resource would be detrimental.
In general, I always check for "IsNot Nothing" for non-value type objects.
Whether it would require to seed nothing-ness checks everywhere, it's just a matter of proper code factoring.
This is MHO: YMMV.
@Padanian
I think the whole discussion here is about good programming practice.
The ideal of "good programming practice" would say that you obviously shouldn't attempt to add two instances of System.Random
. But we're all human, so when we try to write the following either by mistake, or because we're trying to accomplish something specific:
Din rnd As New Random, rnd1 As New Random
Console.WriteLine(rnd + rnd1)
the compiler complains that there is no such operation defined for the Random
type. But an essential prerequisite for the compiler to be able to catch this, is that we indicate that rnd
and rnd1
are of type Random
; the following code would compile just fine (with Option Strict Off
):
Dim o As Object = New Random, o1 As Object = New Random
Console.WriteLine(o + o1)
and would only fall at runtime.
This is what null reference type handling brings to the table: a way to indicate that a variable can be Nothing
or not, and then preventing operations that might violate that contract.
@zspitz Forbidding alcohol to everybody because a minority could get drunk sounded a good idea at first. Been there, done that.
Which is why nullable reference types is opt-in: you can choose not to use this feature entirely.
@Padanian Were you in the forbidden? Or in the minority? 😊
But I don't quite understand what you're trying to say. Nobody is proposing that Nothing
be disallowed; only that a variable that might contain Nothing
be declared as such, and prevented from being misused. By (really bad) analogy, you're not allowed to sell alcohol to minors, therefore you don't have to give them a breath analysis test; and someone who is not a minor must take such a test before operating heavy machinery.
Alright, we made our point clear. No need to further discuss the matter. Thanks for your patience. As for the breath test to minors, oh god you're so wrong.
@Happypig375
Obviously neither Object O nor Console A are initialized or instantiated... but I'm not sure what the point is. Furthermore I'm not clear how the "Nullable Reference Types" (a HORRIBLE name for something that's actually supposed to enable NON Nullable types) feature being added to C# would change anything in your two scenarios. As I understand it (and could definitely be wrong) so the compiler will give you a warning about EVERY possible access of something that COULD be Null\Nothing.
Dim A as Decimal = 10 Dim B as Decimal Dim C as Decimal
C = A / B
Would we want the compiler to give us warning EVERYTIME we do a division about POSSIBLY dividing by zero?
As I understand it (and again could definitely be wrong), the feature being added to C# is to enable types that CAN'T be null\nothing so you don't have to bother adding code for null\nothing checks. While that makes sense, it seems you're still going to have lots of un-instantiated objects that will still need the checks soooo... ?
@WolvenRA I think @Happypig375 's point is that there is no default value to which reference types can be initialized. Even after you've initialized your immediate variable with an an instance of an object, the individual properties also have the same problem -- if those properties are of reference types, they also need to be initialized. IOW, the following:
Then ANY and ALL properties, fields, etc. SHOULD be set to either some predetermined value OR to the base default value for that property\field type... NOT NOTHING!
is impossible.
Furthermore I'm not clear how the "Nullable Reference Types" ... feature being added to C# would change anything in your two scenarios.
Because the compiler warns on a class with uninitialized fields. In the A
class there would be a warning about O
; in the B
class, about A
; and in the C
class, about A
.
the compiler will give you a warning about EVERY possible access of something that COULD be Null\Nothing.
Actually, it only warns about the first access of a given variable within the current scope; once you fix that warning, the next warning lights up. And the compiler detects many cases (there may be others) where even though the CLR type can contain Nothing
, the variable will (usually) not be Nothing
:
If the variable has been declared without the nullable annotation (?
) -- the compiler will warn on missing initialization, or possible Nothing
assignment to the variable; but there will be no warnings on any member access from the variable itself.
Dim rnd As Random ' warning Dim rnd1 As Random = Nothing ' warning Dim rnd2 As Random = (Function() Nothing).Invoke ' warning
Console.WriteLine(rnd.Next, rnd1.Next, rnd2.Next) ' no warning
Even with the annotation, if the variable has been assigned to in the current scope with a presumed non-Nothing
instance
Dim rnd As Random? rnd = New Random Console.WriteLine(rnd.Next) ' no warning
With the annotation, if the variable has been tested as not Nothing
Dim rnd As Random? ' some code If rnd IsNot Nothing Then Console.WriteLine(rnd.Next) ' no warning
Would we want the compiler to give us warning EVERYTIME we do a division about POSSIBLY dividing by zero?
Perhaps. However, I would suggest division by zero is a little different, because
0
has possible meaning in almost every other context that an Integer
can be used -- addition, multiplication, use in a default property, ToString
. In contrast if I have a variable of type Random
which points to Nothing
, I cannot do all the stuff I could do with a Random
; the only thing I can safely do is check that the variable doesn't point to Nothing
. It's reasonable to think of Nothing
as a different type than Random
, particularly since the following prints True
:
Dim o As Object = Nothing If TypeOf o IsNot Object Then Console.WriteLine(True)
the feature being added to C# is to enable types that CAN'T be null\nothing so you don't have to bother adding code for null\nothing checks. While that makes sense, it seems you're still going to have lots of un-instantiated objects that will still need the checks
Only for those places where your design mandates the possibility of Nothing
, which is something you should be doing anyway. The feature only encourages you to write those null-checks.
Also (as I noted above) there is a warning on classes with fields which aren't supposed to contain Nothing
but aren't initialized in the constructor or the field declaration. This prevents classes from having fields with a non-nullable type that are uninitialized.
I'm beginning to wonder if maybe the VB community needs to create an independent VB development team. The team would need to consist of sub teams that work on the various components of the entire development tool chain. If I'm not mistaken, (although I could be), it seems like pretty much the entire tool chain for .Net and .Net Core is supposedly Open Source... but I don't know about the Visual Studio IDE. VS Code is open source but it doesn't contain a number of the components needed to create the entire solution\package.
In any case, why couldn't we make a Fork of the entire development tool chain and control our own destiny? Including incorporating VB into the new .Net Core web development pieces (MVC, Web API, Razor, WebForms, etc.) as well as other portions of .Net Core. In short, Actually Fulfilling the promise Microsoft gave us at the beginning of .Net to keep VB essentially equal to C# through their "Co-Evolution" strategy.
The reason I think we might need to do this is because Microsoft is clearly bailing out of their commitment to VB. While I think this is complete cowardice and blatant treachery on Microsoft's part, we have to face the facts. Just as they shafted the original VB developers, they are now heading down the same path with the VB.Net developers. And just as it cost them thousands of loyal VB developers, I have no doubt it's going to cost them thousands more loyal VB.Net developers. But apparently Microsoft doesn't need the VB.Net developers or the millions of business clients using applications written in VB.Net... (Python anyone?)
I think one of the reasons we don't see as much participation in this Github VBLang community is because most VB.Net developers are business application developers... not system developers. i.e. we don't write Compilers, OS's, Runtimes, Drivers, etc... Consequently most of us (myself included) don't have the background or experience to be able to actively participate in the development of Roslyn, the Framework, the CIL, the Runtime, the VB Compiler etc.. Nor the time. We counted on Microsoft for that. Hard to imagine why we feel stabbed in the back...
Apparently we will have to step up and do it ourselves. While I'm sure I could learn how to help write all these development chain tools, I quite frankly don't have the time or desire. BUT! Since I'm sick and tired of being dependent on an unreliable Microsoft, I would be willing to pay a reasonable annual fee to an INDEPENDENT, DEDICATED, COMPETENT, VB Development team to do it for me.
So, How many others would be willing to support such a team?
Question for Kathleen or one of the other top MS people... How many developers does MS actually have working on the various .Net components specifically for VB?