Convert code snippet from VB.NET to C# - c#

I have tried a number of freely available code converters to convert the following piece, however without success.
Dim resultList = ((From e In p_Xml.Elements()
Where UCase(e.Name.LocalName) = searchName).Union(
From a In p_Xml.Attributes()
Where UCase(a.Name.LocalName) = searchName
Select <<%= propertyName %>><%= a.Value %></>)).ToList()
I think I got it here
var resultList = (from e in p_xml.Elements()
where e.Name.LocalName == searchName
select propertyName).
Union(from a in p_xml.Attributes()
where a.Name.LocalName == searchName
select a.Value).ToList();

Your conversion left out UCase, whose equivalent in C# is ToUpperCase.
This is not the recommended way to perform case-insensitive string comparisons, though.
e.Name.LocalName == searchName
should be replaced with something like:
String.Compare(e.Name.LocalName, searchNamename, StringComparison.InvariantCultureIgnoreCase) == 0
Also, what is propertyName? Whatever it is, its value is obviously not dependent on e. You're selecting one and the same thing for every e in your first query, which makes no sense. I guess you meant select e.
What you probably want then is something along the lines of:
var resultList = (from e in p_xml.Elements()
where String.Compare(e.Name.LocalName, searchName, StringComparison.InvariantCultureIgnoreCase) == 0
select e).
Union(from a in p_xml.Attributes()
where String.Compare(a.Name.LocalName, searchName, StringComparison.InvariantCultureIgnoreCase) == 0
select a.Value).ToList();
I'm only not sure how to represent Select <<%= propertyName %>><%= a.Value %></> in C#, since I don't know VB.

I heard from Microsoft's Roslyn project in a presentation. Maybe that can help you.
Microsoft want to integrate Roslyn in a future Visual Studio version. Then it would be possible to just copy code from VB to clipboard and paste it as C# code. There was also a presentation about that in last year, maybe the same one.

Good online Code Converter that I use all the time is http://www.developerfusion.com/tools/convert/vb-to-csharp/

Related

How to construct dynamic LINQ query string be for a query that looks like *abc*def*

I am using Dynamic LINQ for one of my projects to filter arrays. Library can be downloaded from
NuGet Gallery link or
Codeplex link.
I am using version 1.0.6 from NuGet link. It is the same as LINQ but the condition can be specified using strings. Eg : myArray.Where(myDynamicQueryString)
I build QueryStrings on the fly based on left, right expressions and operators. For example, if my query is
abc < 3, My dynamic query string will be (abc < 3)
xyz == 5.0, myDynamicQueryString will be (xyz = 5)
def == "Name", myDynamicQueryString will be (def = "Name")
var == "Str*", myDynamicQueryString will be (var.StartsWith("Str"))
var == "*Str", myDynamicQueryString will be (var.EndsWith("Str"))
var == "*Str*", myDynamicQueryString will be (var.Contains("Str"))
Now, what should query string be for a query like *abc*def*?
I know it means, it could start with anything, end with anything and have anything in between abc and def, but abc and def should appear in that particular order. But, how do I translate that into a query representation using StartsWith/EndsWith/Contains(These are the ones I know, Please let me know if there are any others I can use)
It looks like what you need is IndexOf. This returns the starting index of the substring, if it exists, otherwise -1.
var.Contains("abc") && var.Contains("def") &&
var.IndexOf("abc") > var.IndexOf("def")
For example, if we use the string XabcXdefXabc, var.IndexOf("abc") will yield 1 and var.IndexOf("def") will yield 5.

Using LINQ to retrieve value from XML (Multiple selection)

I'm trying to convert this VB.Net LINQ to C# LINQ.
Basically, what the end solution is trying to achieve is to to take in an XML file; see snippet:
<BasicFee>
<TrialType>Trial</TrialType>
<A>1326.85575</A>
<B>992.409</B>
<C>668.67075</C>
<D>1260.50925</D>
<E>318.8955</E>
<F>323.30925</F>
<G>323.30925</G>
<H>323.44125</H>
<I>323.169</I>
<J>1326.85575</J>
<K>932.877</K>
</BasicFee>
And by passing parameters, "Trial" and "B", the result would give me this value "992.409" (result from Trial / B).
EDIT - This VB is not the correct syntax to achieve the result. Please see the accepted answer.
The VB equivalent is apparently something like this;
Dim sResult As String = (From oRecord In oXML.Descendants("BasicFee") Where oRecord.< Name >.Value = "Trial").FirstOrDefault.< B >.Value
I have tried tons of different ways and I keep getting the same result (either the Trial element OR the A element values (not being able to use them both).
I was hoping there would be something similar to this:
var example = root.Elements("BasicFee").Elements().Where((c=>c.Value == "Trial" && c.Value == "A"));
Any ideas?
Thanks.
As noted in comments, your VB example wouldn't work either, but it's pretty simple to do in both languages. You need to distinguish between names and values, and exactly how your filtering works:
var example = root.Elements("BasicFee")
.Where(x => (string) x.Element("TrialType") == "Trial")
.Select(x => (string) x.Element("B"))
.FirstOrDefault();
Or with C# 6 you could use:
var example = root.Elements("BasicFee")
.FirstOrDefault(x => (string) x.Element("TrialType") == "Trial")
?.Element("B")?.Value;
The value will be null if there's no such element (either no matching BasicFee or no B element within it).
To find the BasicFee that has that trial type and B value, in C#:
var trialType = "Trial";
var propertyName = "B";
var query = oXML.Descendants("BasicFee")
.Where(bf => (string)bf.Element("TrialType") == trialType)
.Select(bf => (string)bf.Element(propertyName))
.SingleOrDefault();
The VB version on the other hand, could be written like so:
Dim trialType = "Trial"
Dim propertyName = "B"
Dim query =
(From bf In oXML...<BasicFee> ''// ... equivalent to Descendants
Where bf.<TrialType>.Value = trialType
Select bf.Element(propertyName).Value).SingleOrDefault

Optimize Linq in C#

I have columns list in which I need to assign Isselected as true for all except for two columns. (Bug and feature). I have used this following code to achieve it and working fine, but is there any quick or easy way to achieve the same?
DisplayColumns.ToList().ForEach(a => a.IsSelected = true);
DisplayColumns.ToList().Where(a => a.ColumnName == "Bug" || a.ColumnName == "Feature").ToList().ForEach(a => a.IsSelected = false);
Thanks in advance
I have used this following code to achieve it and working fine, but is there any quick or easy way to achieve the same?
Well there's a cleaner way to achieve it in my view - just don't use lambdas etc at all:
foreach (var item in DisplayColumns)
{
item.IsSelected = item.ColumnName != "Bug" && item.ColumnName != "Feature";
}
You can make the decision in one go - it's false if the column name is either "bug" or "feature"; it's true otherwise. And you don't need to call ToList and use ForEach when the C# language has a perfectly good foreach loop construct for when you want to execute some code using each item in a collection.
I love LINQ - it's fantastic - but its sweet spot is querying (hence the Q) rather than manipulation. In this case only the ToList part is even part of LINQ - List<T>.ForEach was introduced in .NET 2.0, before LINQ.
Sure, you can assign the IsSelected at once.
DisplayColumns.ToList().ForEach(a => a.IsSelected = !(a.ColumnName == "Bug" || a.ColumnName == "Feature"));
Provided that DisplayColumns isn't a projection of an anonymous type (in which case the properties are not re-assignable), you'll be able to change the flag in a single pass iteration through the collection.
You can also use Contains to ease the comparison. At class scope:
private static readonly string[] _searches = new [] {"Bug", "Feature"}
In your method:
DisplayColumns
.ToList() // For List.ForEach, although not #JonSkeet's caveat re mutating in Linq
.ForEach(a => a.IsSelected = !_searches.Contains(a.ColumnName));
Edit
As others have mentioned, creation of a new list simply to gain access to .ForEach to change objects in the (original) collection is wasteful and changes will be lost on a collection of value types. Rather, iterate over the original collection with foreach (or even for).
Firstly you only need to call ToList() once when creating a collection from your IEnumerable.
doing this after each operator is costly and redundant.
Secondly just change your condition . all true except for the tow.
DisplayColumns.Where(a => a.ColumnName != "Bug" && a.ColumnName != "Feature").ForEach(a => a.IsSelected = true).ToList();
Edit :
I'm sorry i like a part john's answer since this can be a re occurring thing , or IsSelected could be a Nullable , any ways lets keep it as general as possible .
I also like Stuart's approach , with the collection ( i also thought of it but didn't want to confuse . so let's give the best of all worlds.
when using linq we are actually building an expression tree at the end of which we can choose to materialize into a collection.
there for _searchs can change and each time we materialize that expression we do it with the values currently in that collection , thous making our code much more general .
private static readonly string[] _searches = new [] {"Bug", "Feature"}
DisplayColumns.ForEach(a => a.IsSelected = !_searchs.Contains(a.ColumnName)).ToList();
I'm assuming ForEach is an Extension method for type IEnumrable
Maybe this:
tmp = DisplayColumns.ToList();
var res = tmp.Except(tmp.Where(a => a.ColumnName == "Bug" || a.ColumnName == "Feature"));
foreach(var x in res) x.IsSeleceted = true;
Without using foreach
DisplayColumns
.Select(s=> {
s.IsSelected = (s.ColumnName == "Bug" && s.ColumnName == "Feature");
return s;
});

c# lambda expression convert from vb to c#

I'm trying to convert this vb.net code to c#.
If (txtCompanyName.Text.Trim() <> String.Empty) Then
decals = decals.Where(Function(d As CT_Decal) (From c In db.CT_Companies Where c.CompanyName.Contains(txtCompanyName.Text.Trim()) Select c.CompanyID).ToList.Contains((From t In db.CT_Tanks Where t.CargoTankID = d.TankID Select t.CompanyID).Single.ToString()))
End If
In c# I tried to put the code:
if (txtCompanyName.Text.Trim() != string.Empty)
{
decals = decals.Where(Function(CT_Decal d)(from c in db.CT_Companies
where c.CompanyName.Contains(txtCompanyName.Text.Trim())
select c.CompanyID).ToList().Contains((from t in db.CT_Tanks where t.CargoTankID == d.TankID
select t.CompanyID).Single.ToString()));
}//end if
c# errors:
The name function does not exist and
CT_Decal is a type but is used like a variable.
Does anybody know how to convert this properly?
Without access to your DBContext it's hard to give you an exact query, ignoring the inefficiency of the query you're using.
From what we have, I expect the following code gets pretty close to what you want, or at least should get you started:
if (!String.IsNullOrWhiteSpace(txtCompanyName.Text))
{
var result =
decals.Where(
d => (
from c in db.CT_Companies
where c.CompanyName.Contains(txtCompanyName.Text.Trim())
select c.CompanyID
).Contains(
(from t in db.CT_Tanks where t.CargoTankID == d.TankID select t.CompanyID).Single()));
I expect this will function exactly the same if you've setup your DBContext correctly:
if (!String.IsNullOrWhiteSpace(txtCompanyName.Text))
{
IEnumerable<Decal> result =
decals.Where(d => string.Equals(d.Tank.Company.CompanyName, txtCompanyName.Text.Trim());
your problem is in the keyword function within the where clause.
You must write something like this .Where(d=>(....)). Please see 'jessehouwing' reply.
The syntax .Where(function(f) ....) is a VB.Net equivalent of the lambda expression in C#.
The lambda expression .Where(d => (...)) means 'd' goes to (some action or expression ).
Let me know if this helps.

Select Single Value with ADO.Net Data Services and LINQ

Trying my hand at ADO.Net data services. All the examples shows how to retrieve lists but how would you go about retrieving a single value? e.g. Product X's Price.
Here is the LINQ query i use:
var qry = (from p in
svcContext.Products
where p.ProductName == "Chair"
&& p.Colour == 1
select c) as DataServiceQuery;
Product returnedProd;
qry.BeginExecute(
(pr) => returnedProd = qry.EndExecute(pr).First(), null);
Here i try to retrieve the product and load it into a local variable, but the local var stays null.
Pretty sure, i'm doing it completely wrong :)...any help would be greatly appreciated.
It's not suppose to be
var qry = (from p in svcContext.Products where p.ProductName == "Chair" && p.Colour == 1 select p) where did you declare the c ?
Sorry was supposed to be
var qry = (from p in
svcContext.Products where
p.ProductName == "Chair" && p.Colour
== 1 select p) as DataServiceQuery< Product >;
First() should throw an exception if the result set is empty - are you sure the query is even executing?
You are not the first to get hit by the asynchronous nature of all silverlight outgoing requests.
In the lambda expression
(pr) => returnedProd = qry.EndExecute(pr).First()
you capture the local variable returnedProd but usually the thread that will spin off AFTER BeginExecute has been called will be too late. It will probably executed after the execution goes out of scope of the current method and the variable will be lost.
The solution is to use effectively the "returnedProd" to populate the UI or whatever you need to do IN the lambda expression. Something like :
(pr) => {
returnedProd = qry.EndExecute(pr).First();
MessageBox.Show("Retrieved record" + returnedProd.Id);
}
Otherwise useful answer for the community, I wish I had one a few weeks ago :(

Categories