How to write Subset ⊆ in an operation - vb.net

I want to perform logic operation to check if a string or a set of numbers is contained in a variable. In the same manner simply write:
a + b
a * b
a = b
Is there a way to write something like:
a ⊆ b
I expect te retrieve a boolean result out of it, stating true or false to determine if it is contained in the other variable. I am writing a comparison tool and would like to simplify it to use a math or logic operator instead of a method like InStr().

You can use LINQ for this:
Dim bContainsAllA As Boolean = Not a.Except(b).Any()

You can't create new operators... Your options is to use an existing operator, create a method or do an extension method.
I wouldn't recommend using InStr since this is old VB. There are good methods in the String class. Or use LINQ.

Related

VB.NET + LINQ: Save in a single class attribute the result of querying two columns from different tables

I have two tables: Estructura (with two fields I want: descripcion_morologica and interpretacion) and estrato (with two fields I want: descripcion_larga and interpretacion_explic). On the other side I hace a class in VS with the attributes descripcion and interpretacion. Both tables have a common field called id_excavacion, which I pass to the method as a parameter.
What I'm trying to achieve is to make a query which saves in the "descripcion" attribute the results of t1.descripcion_morfologica and t2.descripcion_larga and also saves in "interpretacion" the results of t1.interpretacion and t2.interpretacion_explic.
So far, I've tried like this:
'GET: api/Excavacions/ListadoUE/5
<Route("api/Excavacions/ListadoUE/{idExcavacion}")>
Function GetListadoUEs(ByVal idExcavacion As Integer) As IQueryable(Of ListadoUEDto)
Dim listado =
From estru In db.Estructura
Join estra In db.Estrato On estra.id_excavacion Equals estru.id_excavacion
Where estru.id_excavacion = idExcavacion
Select New ListadoUEDto With {
.Descripcion = estru.descripcion_morfologica And estra.descripcion_larga,
.Interpretacion = estru.interpretacion And estra.interpretacion_explic
}
End Function
But I only get null, despite the id I pass actually exists.
Thanks a lot in advance!!
You should almost certainly not be using And there. That is a Boolean operator, for combining True and False values. As is always the case, if you want to concatenate Strings then you use &, which is the string concatenation operator.
You should have Option Strict On and then the compiler would have warned you that you were doing something that doesn't make sense. You should turn it On in the project properties and also in the VS options, so it is On by default for future projects. That will force you to put more thought into what data types you use and, therefore, make you write better code.

Multiple assignment in single doesn't work

I am a C# guy working in VB.net. I am used to do it
lblErrorMsg.Text = txtErrorMsg.Value = vDataRow.Item("error_msg")
but it doesn't work in VB.Net. It sets
lblErrorMsg.Text = "False" and txtErrorMsg.Value = "" instead of actual value of vDataRow.Item("error_msg").
What's going on here?
In VB.NET that doesn't work, but i also dont like it in C#. In VB the = operator has two different purposes:
assignment operator
comparison operator (equal to)
So you are assigning the result of the comparison(which is a Boolean) to the String variable.
So you have to use this readable approach:
txtErrorMsg.Value = vDataRow.Item("error_msg") ' doesn't compile with Option Strict On (see below)
lblErrorMsg.Text = txtErrorMsg.Value
But another thing is more important, you should always set Option Strict to On, especially if you're already used to it because you are using C#. You have set it to Off because vDataRow.Item("error_msg") returns Object not String and even your comparison-assignment assigns a Boolean instead of resulting in a compiler-error. Use this instead:
txtErrorMsg.Value = vDataRow.Field(Of String)("error_msg")
In VB.NET treats the single equals in the r-value as a comparison. Hence its not possible to chaining assignment in VB

VB.NET: Lambda expression, use assignment operator instead of equality

I have a method that takes an System.Action, this is what I'm trying to feed it:
Function() Me._existingImports = Me.GetImportedAds()
The thing is that it complains about the = sign since it thinks I'm trying to do a comparison, which I'm not. I want to assign the Me._existingImports the value of Me.GetImportedAds(), but VB.NET complains about DataTable not having a = operator.
How can I force it to use the assignment operator instead of the equality operator?
In C# this works perfectly fine:
() => this.existingImports = this.GetImportedAds()
For now the solution will be to use a standalone method, but that's way more code than needed.
When using Function(), you really define an anonymous function which means you map values to values.
Therefore Function() strictly needs an expression (like x or 42 ...) as the body, which an assignment is not! (Assignments don't evaluate to values like in C-style languages in VB)
Thus what you need is not a Function() but a Sub(), which contains statements (actions) rather than values.
Sub() Me._existingImports = Me.GetImportedAds()
C# doesn't distinguish here, the (much nicer) ... => ... syntax covers it all.

How to access the object itself in With ... End With

Some code to illustrate my question:
With Test.AnObject
.Something = 1337
.AnotherThing = "Hello"
''// why can't I do this to pass the object itself:
Test2.Subroutine(.)
''// ... and is there an equivalent, other than repeating the object in With?
End With
There is no way to refer to the object referenced in the With statement, other than repeating the name of the object itself.
EDIT
If you really want to, you could modify your an object to return a reference to itself
Public Function Self() as TypeOfAnObject
Return Me
End Get
Then you could use the following code
With Test.AnObject
Test2.Subroutine(.Self())
End With
Finally, if you cannot modify the code for an object, you could (but not necessarily should) accomplish the same thing via an extension method. One generic solution is:
' Define in a Module
<Extension()>
Public Function Self(Of T)(target As T) As T
Return target
End Function
called like so:
Test2.Subroutine(.Self())
or
With 1
a = .Self() + 2 ' a now equals 3
End With
I suspect you'll have to repeat yourself. If the expression (to get the object) is expensive, then perhaps drop it into a variable first, and either use that variable in the With, or drop the With completely:
tmp = Test.AnObject;
tmp.Something = 1337;
...
Test2.Subroutine(tmp);
As others have said, you're going to have to write
Test2.Subroutine(Test.AnObject)
This is a good example of why it's worth being a little careful with the With construct in VB.Net. My view is that to make it worth using at all, you really need to be setting more than one or two properties, and/or calling more than one or two methods on the object in the With statement.
When there are lots, and you're not interspersing the .SomeProperty = , or .DoSomething, with other things, it's a terrific aid to readability.
Conversely, a few dots sprinkled amongst a load of other stuff is actually a lot harder to read than not using With at all.
In this case, . characters on their own could easily get lost visually, although of course, it would be syntactically consistent.
I guess they just chose not to implement it. VB isn't really the sort of language where they want to encourage single character language elements, and as a heavy user of VB.Net, I broadly agree with that.
Bottom line: if you're using a With clause with many contained elements, having to refer to the object itself isn't that big a deal. If you're using it with just one or two, maybe better not to use a With clause in the first place.
I'm not sure this is an "answer", per se, but it does illustrate another reason to want a short-hand reference to the parent in a With.
Here's a code sample using a "bare With" (that's what I call it, anyway):
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = .lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
But you actually can't code that because in the term .Start = .lblLinkLabel.Text.IndexOf("link") the compiler expects anything starting with . to be a member of LinkLabel.Link, which .lblLinkLabel isn't.
What would be good, I think, is to be able to write something like:
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = Me.lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
where Me in this scope is taken to be New frmMySubForm.
Yes, I realize that I'm being picky and I could easily assign a variable, etc. But the example form is something I use a lot simply out of preference.

Is there a conditional ternary operator in VB.NET?

In Perl (and other languages) a conditional ternary operator can be expressed like this:
my $foo = $bar == $buz ? $cat : $dog;
Is there a similar operator in VB.NET?
Depends upon the version. The If operator in VB.NET 2008 is a ternary operator (as well as a null coalescence operator). This was just introduced, prior to 2008 this was not available. Here's some more info: Visual Basic If announcement
Example:
Dim foo as String = If(bar = buz, cat, dog)
[EDIT]
Prior to 2008 it was IIf, which worked almost identically to the If operator described Above.
Example:
Dim foo as String = IIf(bar = buz, cat, dog)
iif has always been available in VB, even in VB6.
Dim foo as String = iif(bar = buz, cat, dog)
It is not a true operator, as such, but a function in the Microsoft.VisualBasic namespace.
If() is the closest equivalent, but beware of implicit conversions going on if you have set Option Strict off.
For example, if you're not careful you may be tempted to try something like:
Dim foo As Integer? = If(someTrueExpression, Nothing, 2)
Will give foo a value of 0!
I think the ? operator equivalent in C# would instead fail compilation.
Just for the record, here is the difference between If and IIf:
IIf(condition, true-part, false-part):
This is the old VB6/VBA Function
The function always returns an Object type, so if you want to use the methods or properties of the chosen object, you have to re-cast it with DirectCast or CType or the Convert.* Functions to its original type
Because of this, if true-part and false-part are of different types there is no matter, the result is just an object anyway
If(condition, true-part, false-part):
This is the new VB.NET Function
The result type is the type of the chosen part, true-part or false-part
This doesn't work, if Strict Mode is switched on and the two parts are of different types. In Strict Mode they have to be of the same type, otherwise you will get an Exception
If you really need to have two parts of different types, switch off Strict Mode (or use IIf)
I didn't try so far if Strict Mode allows objects of different type but inherited from the same base or implementing the same Interface. The Microsoft documentation isn't quite helpful about this issue. Maybe somebody here knows it.
If(<expression>, <expressionIfNothing>)
If <expression> evaluates to a reference or Nullable value that is not Nothing, the function returns that value. Otherwise, it calculates and returns <expressionIfNothing> (Intellisense)
This is useful for checking that a particular value exists, and if not replacing it.
Example:
If(cat, dog)
Here, if the cat is not null, it will return cat. If it is null, it will return dog. Most of the time you will be using a ternary operator for this scenario. However, if you do not want to return the value you are testing you will have to use this instead:
If(condition, cat(true), dog(false))