Why does it compile? - c#

var cv = (new CustomValidator()
{
ErrorMessage="Formato de telefone inválido",
ControlToValidate = "txtTelefoneIni", //<-- see the extra comma
});

Because it is legal syntax.
Really, it is.
When you're constructing an object using the object initializer syntax, you're allowed to leave a trailing comma after the last item, even if you end the initializer block there and then.
The reason behind it is probably that it makes it easier to come back and edit it later, as forgetting to add a comma after the previously-last-item is the #1 compile-time-problem with object-initializers.

It's intentional. Also works on enum members. (so it's easier to add more stuff)

Why should it not compile?
This type of syntax is legal in Python as well.

It compiles because it is valid C# syntax. You can also do the same thing with arrays
string[] meh = { "a", "b", "c", };

It is part of the C# language specification: Object initializers.

Because it's allowed.
Generally, allowing trailing comma in such forms (and actually using that "privilege") is useful so that programmers can add more items to the list without the risk of having forgotten to add comma at the end of the previous item.

Its a valid syntax in C#
lets see
var c = new List<int>() { 1, 2, 3 ,};

FWIW, it was already valid in C.
My favorite reason to use such a syntax (especially when defining enums) is that when you add an item to the list, the source control sees changes in one line only (the new one). It doesn't tag the previusly one as modified (because of added comma). Much more readable diff.
My 2-cents.

Related

DocumentDb cannot handle hyphen (-) in column names

I am saving this following XML to DocumentDB:
<DocumentDbTest_Countries>
<country>C25103657983</country>
<language>C25103657983</language>
<countryCode>383388823</countryCode>
<version>2015-08-25T08:36:59:982.3552</version>
<integrity>
<hash-algorithm>sha1</hash-algorithm>
<hash />
</integrity>
<context-info>
<created-by>unittestuser</created-by>
<created-on>2015/08/25 08:36:59</created-on>
<created-time-zone>UTC</created-time-zone>
<modified-by>unittestuser</modified-by>
<modified-on>2015/08/25 08:36:59</modified-on>
<modified-time-zone>UTC</modified-time-zone>
</context-info>
</DocumentDbTest_Countries>
Which gets saved fine to the DocumentDB as following:
{
"DocumentDbTest_Countries": {
"integrity": {
"hash-algorithm": "sha1",
"hash": ""
},
"context-info": {
"created-by": "unittestuser",
"created-on": "2015/08/25 08:36:59",
"created-time-zone": "UTC",
"modified-by": "unittestuser",
"modified-on": "2015/08/25 08:36:59",
"modified-time-zone": "UTC"
},
"country": "C25103657983",
"language": "C25103657983",
"countryCode": 383388823,
"version": "2015-08-25T08:36:59:982.3552"
},
"id": "f917945d-eaee-4eff-944d-dae366de7be1"
}
As you can see the column name is indeed saved with hyphen (-) in it in the DocumentDB (without any kind of errors/exceptions/warning apparently) but then when I try to do a lookup it fails in the Query Explorer. It seems there is no way to search on hyphenated column names. Is this true? or, am I missing something? Can someone please point me to a documentation about this limitation somewhere??
For field names that use certain characters (space, "#", "-", etc.) or which conflict with SQL keywords, you have to use quoted property accessor syntax. So instead of writing:
SELECT * FROM c WHERE c.context-info.created-by = "unittestuser"
write:
SELECT * FROM c WHERE c["context-info"]["created-by"] = "unittestuser"
You can also access properties using the quoted property operator []. For example, SELECT c.grade and SELECT c["grade"] are equivalent. This syntax is useful when you need to escape a property that contains spaces, special characters, or happens to share the same name as a SQL keyword or reserved word.
- is one of those special characters, so to access a property which contains -, you need to use the quoted property operator. It is documented :)
Of course, the idiomatic way would be to use camel casing instead of hyphens, but if you don't want to change your structures, you'll need to use the quoted properties.
For example, using your test data, this query works:
SELECT c["country-code"] FROM root.DocumentDbTest_Countries c
EDIT:
The syntax of the query is a bit confusing, which is what led to most of your problems. Contrary to what you might think,
select * from DocumentDbTest_Countries
doesn't in fact mean "get me all the data in DocumentDbTest_Countries". Instead, it seems to mean "get me all the data in the current collection, and alias it as DocumentDbTest_Countries". This is obvious when you look at the data returned - you'd expect it to return only the fields inside of DocumentDbTest_Countries, but it actually returns all of the values, including the id (which is not a part of DocumentDbTest_Countries - should have been obvious earlier :D).
I don't understand why it's designed as this (even using DocumentDbTest_Countries c to explicitly specify an alias doesn't select DocumentDbTest_Countries), but the fix is to actually start the identifier with the collection name. root is just a way to refer to "this collection", so
select * from root.DocumentDbTest_Countries
returns what you'd expect from the original query. Unless you figure out why the original query behaves the way it does, I'd stick with explicitly using root (or a collection name) as the root every time. It seems to me that using from whatever will always return the current collection, unless you have a collection named whatever - a weird design decision, if you ask me. This means that unless you have a collection named lotsOfFun, the following works the same as using root:
select * from lotsOfFun.DocumentDbTest_Countries
Maybe it's because the top-level object is not named, so they decided that whatever name will work just as well, but that's just an idea.
Well the trick was to use CollectionName.DocumentName instead of just the DocumentName, like this (thanks to #Laan for pointing me in that direction) :):
SELECT * FROM TestProject.DocumentDbTest_Countries c where c["#country"] = "C26092630539"
But then I still miss the Document.Id and Document.SelfLink data in the return Document data.

Comparing Strings in .NET

I am running into what must be a HUGE misunderstanding...
I have an object with a string component ID, I am trying to compare this ID to a string in my code in the following way...
if(object.ID == "8jh0086s)
{
//Execute code
}
However, when debugging, I can see that ID is in fact "8jh0086s" but the code is not being executed. I have also tried the following
if(String.Compare(object.ID,"8jh0086s")==0)
{
//Execute code
}
as well as
if(object.ID.Equals("8jh0086s"))
{
//Execute code
}
And I still get nothing...however I do notice that when I am debugging the '0' in the string object.ID does not have a line through it, like the one in the compare string. But I don't know if that is affecting anything. It is not the letter 'o' or 'O', it's a zero but without a line through it.
Any ideas??
I suspect there's something not easily apparent in one of your strings, like a non-printable character for example.
Trying running both strings through this to look at their actual byte values. Both arrays should contain the same numerical values.
var test1 = System.Text.Encoding.UTF8.GetBytes(object.ID);
var test2 = System.Text.Encoding.UTF8.GetBytes("8jh0086s");
==== Update from first comment ====
A very easy way to do this is to use the immediate window or watch statements to execute those statements and view the results without having to modify your code.
Your first example should be correct.
My guess is there is an un-rendered character present in the Object.ID.
You can inspect this further by debugging, copying both values into an editor like Notepad++ and turning on view all symbols.
I suspect you answered your own question. If one string has O and the other has 0, then they will compare differently. I have been in similar situations where strings seem the same but they really aren't. Worst-case, write a loop to compare each individual character one at a time and you might find some subtle difference like that.
Alternatively, if object.ID is not a string, but perhaps something of type "object" then look at this:
http://blog.coverity.com/2014/01/13/inconsistent-equality
The example uses int, not string, but it can give you an idea of the complications with == when dealing with different objects. But I suspect this is not your problem since you explicitly called String.Compare. That was the right thing to do, and it tells you that the strings really are different!

Object Initialiser Comma Query

Having noticed a small mistake in my C# code (end of line 4):
Domain.Models.Patient patient = new Domain.Models.Patient
{
PatientId = patientId,
StudyID = studyId,
};
I don't get any build error, or runtime errors - when there is an errant comma at the end of studyId.
Why is this, and does it really matter?
It doesn't matter, and it will not cause any compile time error as well. Its true for others as well like enums. It is probably to show, that other items may be added to the object.
enum Test
{
Value1,
Value2,
//Value3, May be to comment out easily
}
Found a Reference - C# Language
Specification:
(Section 24.2) Like Standard C++, C# allows a trailing comma at the end of an
array-initializer. This syntax provides flexibility in adding or
deleting members from such a list, and simplifies machine generation
of such lists.
And
(Section - 21.1) - C# allows a trailing comma in an enum-body, just like it allows one in
an array-initializer
The last comma is ignored by the compiler.
Domain.Models.Patient patient = new Domain.Models.Patient
{
PatientId = patientId,
StudyID = studyId, // this comma is ignored by compiler.
};
This is very convenient when you copy/paste, rearrange, comment out/in your initializers. You don't have to worry if you have to add or remove comma in process.

Is it possible to extend the Query-Keywords in C# / LINQ?

is it possible to extend the query-keywords of Linq (like: select, where, etc.) with own definitions?
Codeexample to make it clearer:
System.Collections.Generic.List<string> aList =
new System.Collections.Generic.List<string> { "aa", "ab", "ba", "bb" };
// instead of
string firstString = (from item in aList
where item.StartsWith("a")
select item).First();
// would be nice
string firstString = from item in aList
where item.StartsWith("a")
selectFirst item;
// or something else
from item in aList
where item.StartsWith("a")
WriteLineToConsole item;
I think it's not possible, but still hoping ;)
You can't add your own contextual keywords, but you can affect what the existing ones mean.
For example, this code:
string firstString = (from item in aList
where item.StartsWith("a")
select item).First();
is effectively preprocessed to:
string firstString = aList.Where(item => item.StartsWith("a"))
.First();
... so if you change what those Where and First method calls mean, you can affect the behaviour.
If you've got the stomach for it, you might want to look at this Stack Overflow answer I wrote a while ago which changes the behaviour of where in LINQ to Entities in certain circumstances. It's evil, evil code though.
One way to achieve this would be to write a pre-processor which will transform your custom LINQ keywords into standard LINQ keywords before feeding it to the compiler. By the way that's how it works with the standard LINQ keywords. A pre-processor converts them into normal extension methods (.Select, .Where, .GroupBy, ...), and then feeds it to the compiler which doesn't understand those keywords.
Of course by doing this you will lose Intellisense, but this could be solved by writing a Visual Studio extension. Could be quite a lot of work though for this sugar.
No, it is not possible within the language spec or any current C# compiler. Anything you create there would no longer be (pure) C#.

Dash (-) in anonymous class member

is it possible to use dash (-) in a member name of an anonymous class? I'm mainly interested in this to use with asp.net mvc to pass custom attributes to html-helpers, since I want my html to pass html5-validation, this starting with data-.
Exemple that doesn't work:
<%=Html.TextBoxFor(x => x.Something, new {data-animal = "pony"})%>
Putting a # in front of the member name doesn't do the trick either.
Update: If this isn't possible, is there a recommended way todo what I want? My current temporary solution is to add a replace to the whole thing like this:
<%=Html.TextBoxFor(x => x.Something, new {data___animal = "pony"}).Replace("___", "-")%>
But that sucks, because it's ugly and will break when Model.Something contains three underscores. Buhu.
Just found this post while searchching for the same problem.
I found this link:
http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Using-custom-data-attributes-in-ASPNET-MVC.aspx
It resolves the problem. It mentions the following:
[...] or better yet, just use code from ASP.NET MVC source:
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes)
{
RouteValueDictionary result = new RouteValueDictionary();
if (htmlAttributes != null)
{
foreach (System.ComponentModel.PropertyDescriptor property in System.ComponentModel.TypeDescriptor.GetProperties(htmlAttributes))
{
result.Add(property.Name.Replace('_', '-'), property.GetValue(htmlAttributes));
}
}
return result;
}
Collecting the Asp-Mvc version specific ways to do data- here:
MVC 3+ : Use an underscore _ and it will be automatically replaced by mvc
MVC 1?,2: see #Jean-Francois answer, which points to this
No, because the dash is a C# operator (minus), and white space isn't significant.
Right now the compiler thinks you are trying to subtract animal from data, which doesn't work unless the - operator is specified for the types in question.
It is not possible to use - as part of any identifier.
http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx
No, you can't use the hyphen character. You need to use alphanumeric characters, underscores, or the other characters described here. '-' is treated as a minus. data-animal would be treated the same as data - animal, so that won't even compile unless you have separately defined data and animal (and it could present subtle bugs if you have!).
Edit: With C#'s capability to have identifiers with Unicode escape sequences, you can get the effect of a dash in an identifier name. The escape sequence for "&mdash" (the longer dash character) is "U+2014". So you would express data-animal as data\u2014animal. But from a coding style point of view, I'm not sure why you wouldn't choose a more convenient naming convention.
Also, another point to highlight from "2.4.2 Identifiers (C#)": You can't have two of these escape sequences back to back in an identifier (e.g. data\u2014\u2014animal).

Categories