VB.NET: Combining assignments (operator syntax) - c#

Take a look at this VB.NET code:
list = GeoController.RegionByCountry(country, language)
Region.allByLanguage(key) = list
In C#, I could write this in one line:
Region.allByLanguage[key] =
(list = GeoController.RegionByCountry(country, language))
Is there a way to make this a one-liner in VB.NET, like I can in C#?
EDIT: You all must need some sleep, or else you might be thinking a little harder.
Region.allByLanguage is a cache.
Here's the context:
Dim list As IEnumerable(Of Region)
Dim key = Region.CacheKey(country, language)
If Region.allByLanguage.ContainsKey(key) Then
list = Region.allByLanguage(key)
Else
list = GeoController.RegionsByCountryAndLanguage(country, language)
Region.allByLanguage(key) = list
End If
Return list
How can you tell me that's not verbose code? Shudders.
Heck, if this was a C# team, I'd just write:
return Region.allByLanguage.ContainsKey(key) ?
Region.allByLanguage[key] :
(Region.allByLanguage[key] = GeoController.RegionsByCountryAndLanguage(country, language));

Do you actually need access to the list instance also? If not, why not just write it like this?
Region.allByLanguage[key] = GeoController.RegionByCountry(country, language));
Your syntax seems strange for C# also, and I don't think many would write that code that way.
Also, it's no goal in itself to reduce the number of lines of code, if it makes the code less readable as you are trying to do in this case.
If you are assigning to both Region.allByLanguage[key] and list, I would prefer two lines of code if I ever were to read your code. Merging both assignments on one line of code seems forced at best, and might have the reader not realize that list is assigned as well as Region.allByLanguage[key].

As an alternative, unless your cache is massive or doing something heavyweight, I would just change the code to something like this:
Dim key = Region.CacheKey(country, language)
If not Region.allByLanguage.ContainsKey(key) Then
Region.allByLanguage(key) = GeoController.RegionsByCountryAndLanguage(country, language)
End If
Return Region.allByLanguage(key)
This way you can avoid the need for single line assignment, and you still reduce the lines of code. You can refactor it back out if performance becomes a problem.

In VB.NET, you cannot assign to a variable and assign that same variable to another variable.
In your code, you're assigning GeoController.RegionByCountry(country, language) to list and then assigning list to Region.allByLanguage[key]
In most cases, this is not a good thing to do as it makes your code more difficult to read.
If you are going to use the list variable later in the subroutine, it is better to go the VB way; explicitly assign the list and then assign it to the region. If you're not going to use it later then just assign result of GeoController.RegionByCountry(country, language) straight away and skip the temporary assignment to the list variable.
If you insist, however on a 'one-liner', you can use this code I was forced to write when I attempted porting some C# code to VB.NET some time ago:
<Extension()> Public Function AssignAndReturn(Of T)(ByVal source As T, ByRef target As T) As T
target = source
Return target
End Function
You can use it like so:
Region.allByLanguage(key) = GeoController.RegionByCountry(country, language).AssignAndReturn(list)
It evaluates the GeoController.RegionByCountry(country, language), assigns it to the list and then returns the result; which is the list.

Related

Push Item to the end of an array

No, I can't use generic Collections. What I am trying to do is pretty simple actually. In php I would do something like this
$foo = [];
$foo[] = 1;
What I have in C# is this
var foo = new int [10];
// yeah that's pretty much it
Now I can do something like foo[foo.length - 1] = 1 but that obviously wont work. Another option is foo[foo.Count(x => x.HasValue)] = 1 along with a nullable int during declaration. But there has to be a simpler way around this trivial task.
This is homework and I don't want to explain to my teacher (and possibly the entire class) what foo[foo.Count(x => x.HasValue)] = 1 is and why it works etc.
The simplest way is to create a new class that holds the index of the inserted item:
public class PushPopIntArray
{
private int[] _vals = new int[10];
private int _nextIndex = 0;
public void Push(int val)
{
if (_nextIndex >= _vals.Length)
throw new InvalidOperationException("No more values left to push");
_vals[_nextIndex] = val;
_nextIndex++;
}
public int Pop()
{
if (_nextIndex <= 0)
throw new InvalidOperationException("No more values left to pop");
_nextIndex--;
return _vals[_nextIndex];
}
}
You could add overloads to get the entire array, or to index directly into it if you wanted. You could also add overloads or constructors to create different sized arrays, etc.
In C#, arrays cannot be resized dynamically. You can use Array.Resize (but this will probably be bad for performance) or substitute for ArrayList type instead.
But there has to be a simpler way around this trivial task.
Nope. Not all languages do everything as easy as each other, this is why Collections were invented. C# <> python <> php <> java. Pick whichever suits you better, but equivalent effort isn't always the case when moving from one language to another.
foo[foo.Length] won't work because foo.Length index is outside the array.
Last item is at index foo.Length - 1
After that an array is a fixed size structure if you expect it to work the same as in php you're just plainly wrong
Originally I wrote this as a comment, but I think it contains enough important points to warrant writing it as an answer.
You seem to be under the impression that C# is an awkward language because you stubbornly insist on using an array while having the requirement that you should "push items onto the end", as evidenced by this comment:
Isn't pushing items into the array kind of the entire purpose of the data structure?
To answer that: no, the purpose of the array data structure is to have a contiguous block of pre-allocated memory to mimic the original array structure in C(++) that you can easily index and perform pointer arithmetic on.
If you want a data structure that supports certain operations, such as pushing elements onto the end, consider a System.Collections.Generic.List<T>, or, if you insist on avoiding generics, a System.Collections.List. There are specializations that specify the underlying storage structure (such as ArrayList) but in general the whole point of the C# library is that you don't want to concern yourself with such details: the List<T> class has certain guarantees on its operations (e.g. insertion is O(n), retrieval is O(1) -- just like an array) and whether there is an array or some linked list that actually holds the data is irrelevant and is in fact dynamically decided based on the size and use case of the list at runtime.
Don't try to compare PHP and C# by comparing PHP arrays with C# arrays - they have different programming paradigms and the way to solve a problem in one does not necessarily carry over to the other.
To answer the question as written, I see two options then:
Use arrays the awkward way. Either create an array of Nullable<int>s and accept some boxing / unboxing and unpleasant LINQ statements for insertion; or keep an additional counter (preferably wrapped up in a class together with the array) to keep track of the last assigned element.
Use a proper data structure with appropriate guarantees on the operations that matter, such as List<T> which is effectively the (much better, optimised) built-in version of the second option above.
I understand that the latter option is not feasible for you because of the constraints imposed by your teacher, but then do not be surprised that things are harder than the canonical way in another language, if you are not allowed to use the canonical way in this language.
Afterthought:
A hybrid alternative that just came to mind, is using a List for storage and then just calling .ToArray on it. In your insert method, just Add to the list and return the new array.

How Iterate through a list of an object with Lambda Expressions

I have an object, which inside is another object that is a list of an object.
What I am trying to do is iterate through the list and to take each a value from the list to set a label. So, if I have 5 values in my list:
for (x=0; list.count; x++)
{
lblDayOne.Text = list[x].DayOne.Value; <-I want to set this with the value relevant for Day One and so on and so forth for each label as below
lblDayTwo.Text = list[x].DayTwo.Value;
lblDayThree.Text = list[x].DayThree.Value;
lblDayFour.Text = list[x].DayFour.Value;
lblDayFive.Text = list[x].DayFive.Value;
}
Is there a way to do this? I tried with foreach but no luck. This is all C#
Call List<T>.ForEach(). Pass it a lambda.
Enumerable.Range(0,9).ToList().ForEach( n => Console.WriteLine(n) );
UPDATE
Wait a minute, are you trying to iterate not over your list of objects, but over a list of PROPERTIES in each object in the list (DayOne, DayTwo, etc.), and possibly also automagically link them up with variables with similar names? No, there's nothing like that in C#. You'd have to roll your own using reflection, and that would be a lot of work for very little payoff.
You could consider storing those values not as properties, but in a Dictionary<String,String>, or perhaps an array String DayValues[]; either of those would support iteration, but you'd still have the problem of linking up the items programmatically with the label controls. You might be able to look up the controls by name, though, depending how you're doing your UI -- ASP.NET has FindControl(string id), for example.
But what you have above is a perfectly clear, readable way of doing it, just the way it is. That's how I'd do it in production code, except that I'd assign list[x] to a local variable at the top of the loop block to clear up the visual noise a bit. An iterating lambda solution would sacrifice clarity for cleverness, not a good tradeoff in code you'll have to maintain. If it's just fun code, on the other hand, by all means stretch out and learn something new. Lambdas are a fantastic toy.
If that's really the question you're asking, you should edit your question for clarity.

VB.NET Execution Order

I am currently working on converting some VB source code over to C#. While I understand there are converters to automate this, and that I could actually use this particular dll without rewriting it, I'm doing it partially so I can understand VB better. Not so much as to expect to write it, but it's at least helping me to be able to read it.
In doing this though, I've come across something that is quite confusing. The following code snippets are examples, but I've seen it throughout the program.
VB Source Code:
Friend Function AllocateObjectNumber() As Long
AllocateObjectNumber = _nextFreeObjectNumber
_nextFreeObjectNumber += 1
_objectAllocatedCount += 1
End Function
My translated C# Code:
internal long AllocateObjectNumber()
{
cvNextFreeObjectNumber += 1;
cvObjectAllocatedCount += 1;
return cvNextFreeObjectNumber;
}
What I'm not understanding is the flow control that VB uses. I understand that AllocateObjectNumber += 1 is used in place of return cvNextFreeObjectNumber, but if this line comes before the incrementing of the two variables, then how is that code not considered unreachable? Based on my C# understanding, the first line in this method would immediately return to the calling method, and this whole method would basically act as a pseudo-Property.
Any helpful explanations?
The VB approach is more similar to storing the value in a temporary variable:
internal long AllocateObjectNumber()
{
var nextNumber = _nextFreeObjectNumber
cvNextFreeObjectNumber += 1;
cvObjectAllocatedCount += 1;
return nextNumber;
}
In VB the function = value syntax doesn't do a return - so the code after can keep running. When that method reaches the end, then the value you used becomes the 'return' value for whatever called it in the first place.
You can use the function = value syntax multiple times in the same method as a way of returning a different result in different conditions without needing the temporary variable I used in my example.
Based on my C# understanding, the first line in this method would immediately return to the calling method
But it’s not C# code, it’s VB code. AllocateObjectNumber = _nextFreeObjectNumber does not return, it just assigns a return value. The actual return is at the end of the method.
Most people would actually write the VB code identical to the C# code, i.e. using Return explicitly. The assign-to-method-name style is a remnant of older VB versions where it was the only way of returning a value from a function. In VB.NET, you can use both.

C#: How do sequential function calls work? (efficiency-wise)

In C# it's conventional to write in a fairly objective manner, like so:
MyObj obj = new MyObj();
MyReturn ret = obj.DoSomething();
AnotherReturn rett = ret.DoSomethingElse();
I could just write the above like this:
AnotherReturn rett = new MyObj().DoSomething().DoSomethingElse();
However, how does the stackframe work when you have a bunch of function calls in a sequence like this? The example is fairly straightforward but imagine if I've got 50+ function calls chained (this can possibly happen in the likes of JavaScript (/w jQuery)).
My assumption was that, for each function call, a return address is made (to the "dot"?) and the return value (a new object with other methods) is then immediately pumped into the next function call at that return address. How does this work w.r.t. getting to the overall return value (in this example the return address will assign the final function value to rett)? If I kept chaining calls would I eventually overflow? In that case, is it considered wiser to take the objective route (at the cost of "needless" memory assignment?).
It's exactly the same as if you called each method on a separate line, assigning the return value to a variable each time and then using that variable to call the next method.
So your two samples are the same, effectively.
Do you have Reflector? You could try the two methods and inspect the generated IL code to see exactly what differences there are.
Although the 2 calls are same but if you have lot of "Dots" then somewhere it is a code smell (Law of Demeter).
See below discussion

Daisy Chain Methods in C#

I'm new to .NET and C#, coming from a background in Ruby. While I've successfully developed a couple of small applications in C#, I still have a lot to learn. One thing that is puzzling me though, is finding an efficient way to call multiple methods on an object. I'll give an example using strings.
I'm used to being able to do something like this in Ruby:
my_string = "The quick brown fox\tjumped over the lazy dog\t\n"
puts my_string.strip.split("\t")
However, to accomplish the same thing in C#, this Is all I know to do right now:
var myString = "The quick brown fox\tjumped over the lazy dog\t\n";
var myStringTrim = myString.Trim();
var myStringSplit = myStringTrim.Split('\t');
foreach (var s in myStringSplit)
{
Console.WriteLine(s);
}
So, is there a more efficient way to accomplish this in C#?
This particular example makes me wonder what would happen to performance if I were to use this method to read, parse, and process a large text file or something like that.
You can do myString.Trim().Split('\t'); in C#
You can do that, because Trim() returns a string object, which you can then call Split() on, which returns an array.
But it's not necessarily more 'efficient'. Interim objects are being created, even if you aren't storing them in variables.
this works just fine...
var myString = "The quick brown fox\tjumped over the lazy dog\t\n".Trim().Split('\t');
these methods are instance methods of the string object, and will work just as you expect them to do in Ruby.
the one thing to keep in mind is that string is immutable. that is, these methods do not change the original value of the string variable, but return a modified copy of the original.
You can chain these commands together like this:
myString.Trim().Split('\t').ForEach(s => Console.WriteLine(s));

Categories

Resources