In VB.NET you can use an object initializer and reference the same members on the right hand side, like this:
GetValue.Add(New ArrayIndexInfo() With {
.Type = CType(NvpInfo(Index), Type),
.Name = NvpInfo(Index + 2).ToString,
.NvpValues = CType(.Type.GetField(NvpInfo(Index + 1).ToString).GetValue(Instances.First(Function(o) o IsNot Nothing AndAlso o.GetType = CType(NvpInfo(Index), Type))), NameValuePair())
})
Notice how in the line that sets .NvpValues you can reference .Type and that it's no problem.
But if you try to do that in c# (or like I did, try to convert a project from vb.net to c#), you get an error.
<variable> is not declared
I worked around it like this, which is not DRY because ((Type)NvpInfo[Index]) is repeated:
functionReturnValue.Add(new ArrayIndexInfo {
Type = (Type)NvpInfo[Index],
Name = NvpInfo[Index + 2].ToString(),
NvpValues = (NameValuePair[])((Type)NvpInfo[Index]).GetField(NvpInfo[Index + 1].ToString()).GetValue(Instances.First(o => o != null && o.GetType() == (Type)NvpInfo[Index]))
});
Why doesn't c# allow this? I think it should. I think converting legacy code to c# should be as painless as possible.
Is there a better way that I get around this and still use the object initializer?
To answer the question, I'll base myself on a simplified version of your example
VB.NET:
Dim c = New SomeClass With {
.Prop1 = "abc",
.Prop2 = .Prop1
}
Console.WriteLine(c.Prop1) 'prints "abc"
Console.WriteLine(c.Prop2) 'prints "abc"
C#
var c = new SomeClass
{
Prop1 = "abc",
Prop2 = Prop1 // won't compile. Can't reference Prop1 here.
};
Console.WriteLine(c.Prop1);
Console.WriteLine(c.Prop2);
Addressing your last question:
Is there a better way that I get around this and still use the object initializer?
So one of your concerns is that because C# doesn't allow referencing other properties in an object initialization statement, that it causes you to violate the DRY principle. But really, all you need to do is use variables:
Working C# example that doesn't violate DRY principle:
string temp = "abc";
var c = new SomeClass
{
Prop1 = temp,
Prop2 = temp
};
Console.WriteLine(c.Prop1); // prints "abc"
Console.WriteLine(c.Prop2); // prints "abc"
Why doesn't c# allow this? I think it should.
Obviously, only the designers of the language can truly answer that one. But I can at least share why I like C#'s design decision better. For instance, in the VB.NET version, if I mistakenly initialize the properties in a different order:
Dim c = New SomeClass With {
.Prop2 = .Prop1,
.Prop1 = "abc"
}
Console.WriteLine(c.Prop1) 'prints "abc"
Console.WriteLine(c.Prop2) 'prints nothing
... the code is still "legal" but I've now inadvertently introduced a bug, and Prop2 is now initialized incorrectly.
Because C# disallows this, it prevents most bugs related to the order of property initialization. I agree that in this very simplified example it's hard to imagine anyone falling for that mistake. But with more properties and more complicated initialization statements, it may not be so obvious, and mistakes can more easily be made. C# helps you avoid these subtle bugs.
I think converting legacy code to c# should be as painless as possible.
I guess you're implying that VB.NET is a legacy language? Some may take offense :)
But more seriously, are you implying that language design decisions should be made to facilitate migration from other languages? C# and VB.NET are two full featured languages in their own right. They are not meant to have matching and symmetrical language designs. If they did, what would be the point of having 2 separate languages?
No. They are 2 different languages with 2 different philosophies. We should consider ourselves lucky that the migration path is as easy as it is currently. There is no reason why it needs to be.
Related
void Main()
{
Test t = new Test
{
A = "a",
B = "b", // <-- erroneous trailing comma
};
}
public class Test
{
public string A { get; set; }
public string B { get; set; }
}
I find the above typo in my code quite a lot. I'm always suprised that the compiler doesn't seem to care about this. Why is the above not a syntax errror? Is there any actually valid use for it?
I find the above typo in my code quite a lot. I'm always suprised that the compiler doesn't seem to care about this. Why is the above not a syntax errror?
Because the people designing the C# syntax grammar were smart enough to learn the lessons from other programming languages which didn't allow the dangling comma, to the constant irritation of programmers in those languages.
For example, ECMAScript (JavaScript) was silent on the issue initially, and so naturally some implementations (SpiderMonkey in Firefox, Opera's JavaScript, etc.) allowed them while others (Microsoft's JScript) didn't. And so this led to a spate of "why doesn't this work in IE" questions here and elsewhere. (Fortunately, ECMAScript 5 explicitly allows them, and IE8 finally supports them in object initializers -- IE8 still treats array initializers in a non-standard way, though to be fair the dangling comma for those was only clarified in ECMAScript 5, too.)
You find this in lots of other places in the C# grammar too, like enums and array initializers.
It's not an error because it's convenient. To add to the initializer, you only have to add in one line instead of adding a comma to one line and entering a whole new line.
This is actually fairly common in list/array initialization in other languages too (Python, Ruby, Haskell come to mind).
I think it's allowed to simplify automatic code generation.
In this case you can have some sort of your program create code like this
...
for( char c = 'A'; c < 'Z'; c++ )
{
AddToOutput( c + " = \"+c.ToLower()+"\"," );
}
...
And don't have to care about removing the last trailing comma.
One of the common programming best practices is "define variables as close to where they are used as possible".
I use structs frequently to create code thats almost self documenting in places. However, C# forces me to define the struct outside the method. This breaks the aforementioned best practice - its basically creating an unwanted global variable type for the entire class.
Is it possible to define a local struct inside a method, just like a local variable, and if not, could you give me a window into the reasons the C# designers decided to prevent this?
Use Case
I'm converting part of a spreadsheet into C# code. I'd like to use local structs within the method to store temporary information in an organized manner, without having to resort to hundreds of separate variables that are global in scope.
Update 2016-August: C# 7.0 may have this feature!
As of 2016-Aug, apparently, this will be a feature in C# 7.0.
So the C# compiler team agreed - wow!
Update 2020-July: Now supported by C# and C++
C++ has always fully supported this. And it's fantastic.
C# 7.0 now has value tuples for a lightweight data structure with named fields. See answer from Ghost4Man.
I believe it's not permitted to define named types within a method. As to why, I'll have to speculate. If a type is not going to be used outside, then its existence probably cannot be justified.
You can however define anonymous type variables within a method. It will somewhat resembles structures. A compromise.
public void SomeMethod ()
{
var anonymousTypeVar = new { x = 5, y = 10 };
}
It is a little late but this is my solution for lists - using anonymous vars as the structs inside of methods:
var list = new[] { new { sn = "a1", sd = "b1" } }.ToList(); // declaring structure
list.Clear(); // clearing dummy element
list.Add(new { sn="a", sd="b"}); // adding real element
foreach (var leaf in list) if (leaf.sn == "a") break; // using it
Anonymous elements (sn and sd) are somehow read only.
Since C# 7.0, you can use value tuples if you want a lightweight data structure with named fields. They can be used not only locally inside methods, but also in parameters, returns, properties, fields, etc. You can use local functions to somewhat emulate struct methods.
var book = (id: 65, pageCount: 535); // Initialization A
(int id, int pageCount) book2 = (44, 100); // Initialization B
Console.WriteLine($"Book {book.id} has {book.pageCount} pages.");
(int id, int pageCount) = book; // Deconstruction into variables
Console.WriteLine($"Book {id} has {pageCount} pages.");
Here book is of type System.ValueTuple<int, int> (a generic struct).
You could do something like this using anonymous types. MSDN examples below:
var v = new { Amount = 108, Message = "Hello" };
or
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Nowadays, you could also use a named tuple: https://learn.microsoft.com/en-us/dotnet/csharp/tuples
No, this is not possible. If you are using .net 4.0, you could use Tuple<T1, ..., Tn> to replicate such a thing.
I don't see the reason why you would need such a struct - just use variables with speaking names and this shouldn't be any problem at all. In combination with explicit declaration using the class names there is very little space for ambiguity.
You can define an anonymous type within your method and use it. The anonymous type will be readonly, so it gets you the immutability that is desired of structs. It will not explicitly be a struct, but it will be fully defined and contained within your method.
var myLocalType = new
{
SomeValue = "Foo",
SomeId = 14
};
it's not a struct, but mayme a var can help you out here?
var person = new {Name= "John", City = "London"};
it's strong typed so it will be compile time checked
You can create a dynamic type in c# 4.0 to accomplish this task, but its not exactly what you are looking for.
However I believe that the maximum of defining variables as close to where they are used is meant to mean where a variable is introduced into program flow not where the type is declared. I believe that most types have some ability to be reused creating in method types limits you ability to create reusable blocks of code that operates on common data.
For a given class, with a default property of list, you can access an instance object in the list by doing myClass.defProperty("key"). You can also achieve the same results by typing myClass.defProperty!Key.
I have been told that using the parenthesis and quotes is faster for the way the runtime accesses the Property, but I'd like to understand what is the difference and how do each work...
I understand C# has a similar behavior by replacing the parenthesis with square brackets.
Given the following code in Visual Basic.NET:
Dim x As New Dictionary(Of String, String)
x.Item("Foo") = "Bar"
You can access the "Foo" member of the dictionary using any of the following:
Dim a = x!Foo
Dim b = x("Foo")
Dim c = x.Item("Foo")
If you look at the IL under Reflector.NET then you'll find that they all translate to:
Dim a As String = x.Item("Foo")
Dim b As String = x.Item("Foo")
Dim c As String = x.Item("Foo")
So, they are all equivalent in IL and, of course, they all execute at the same speed.
The bang operator only lets you use statically defined keys that conform to the standard variable naming rules.
Using the indexed approaches then your keys can be almost any valid value (in this case string) and you can use variables to represent the key.
For code readability I would recommend the x.Item("Foo") notation as is is very clear as to what is going on. x("Foo") can be confused with a call to a procedure and x!Foo makes the Foo look like a variable and not a string (which it really is). Even the Stack Overflow color-coding makes the Foo look like a keyword!
The C# equivalent for this code is x["Foo"];. There is no ! syntax equivalent.
So, the bottom-line is that ! isn't better or worse on performance and just may make code maintenance more difficult so it should be avoided.
I am making an instructional video for C# 4.0 for beginning programmers.
For every topic I introduce I include a practical example which the student could actually use, for instance, for the improved COM Interop functionality, I show how to create an Excel file and fill it with values from code.
For named and option parameters I show how you can create a logging method with 5 parameters but don't have to pass any if you don't want since they all have default values. So they see how calling methods is easier with this feature.
I would also like to introduce tuples as well if I can, but it seems that all the "practical examples" (as in this question: Practical example where Tuple can be used in .Net 4.0?) are very advanced. The learners that use the video learn OOP, LINQ, using generics, etc. but e.g. functional programming or "solving Problem 11 of Project Euler" are beyond the scope of this video.
Can anyone think of an example where tuples would actually be useful to a beginning programmer or some example where they could at least understand how they could be used by and advanced programmer? Their mechanics are quite straight-forward for a beginning programmer to grasp, I would just like to find an example so that the learner could actually use them for a practical reason. Any ideas?
Here's what I have so far, but it is just dry mechanics without any functionality:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//two ways to define them
var customer = new Tuple<int, string, string>(23, "Sam", "Smith");
var customer2 = Tuple.Create<int, string, string>(34, "James", "Allard");
//with type inference, more concise (only available with the Create keyword)
var customer3 = Tuple.Create(23, "John", "Hoopes");
//you can go up to eight, then you have to send in another tuple
var customer4 = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9, 10));
Console.WriteLine(customer.Item1);
Console.WriteLine(customer2.Item2);
Console.WriteLine(customer3.Item3);
Console.WriteLine(customer4.Rest.Item1.Item3);
Console.ReadLine();
}
}
}
Tuples are not necessarily the first topic I would tackle for beginner programmers ... however, there are some simple examples.
One that comes to mind is returning a value (which may actually be null) from a function that performs a search (or calculation), together with a boolean that indicates whether the result was found or not. It's an approach that avoids using out parameters, which can be cumbersome or problematic in certain scenarios (like LINQ queries):
public Tuple<string,bool> SearchDictionary( string searchKey )
{
string value;
bool wasFound = someDictionary.TryGetValue( searchKey, out value );
return new Tuple<string,bool( value, wasFound );
}
// since <null> is a legal value to store in the dictionary, we cannot
// use it to distinguish between 'value not found' and 'value is null'.
// the Tuple<string,bool>, however, does allow us to do so...
var result = SearchDictionary( "somekey" );
if( result.Item2 )
{
Console.WriteLine( result.Item1 );
}
Another example that I think is natural, is creating associations between two values without creating an explicit class for the purpose. For example, let's imagine we want to represent pairs of opponents who will play tennis matches. We could use:
// note the symmetry in the representation of opponents of a tennis match...
// if the relationship were asymmetrical, tuple may not be the best choice.
var playerA = new TennisPlayer("Serena Williams");
var playerB = new TennisPlayer("Venessa Williams");
var match = new Tuple<TennisPlayer,TennisPlayer>( playerA, playerB );
Creating a class for something like this can be avoided by using tuples instead.
A final example, is using tuples to represent composite keys in a dictionary. Since Tuple<>s can be compared to one another for equality, it becomes possible to do stuff like:
var complexDictionary =
new Dictionary<Tuple<string,int,decimal,DateTime>,string>();
complexDictionary.Add( new Tuple("USA",-4,1.671,DateTime.Now), "active" );
EDIT: One comment I would make when educating developers about the use of tuples, is that tuples should rarely (if ever) appear in the public interface of code you expect others to consume. As tools to simplify the internal implementation of a class or module, I think they're fine. But once you start passing them in or out of methods that developers consuming your code have to interact with, you run in the problem that tuples obscure the semantics of your API. It becomes hard for developers to interpret what Tuple<int,int> is supposed to mean. What do Item1 or Item2 mean in such a case? When you see yourself needing to pass tuples in or out of methods, you should strongly consider writing a class to encapsulate and clarify the relationship.
The best practical reason i can see is using them as temporary "classes". You want to associate multiple pieces of information, but not create yet another class structure to hold them.
They should be temporary, because if you're using them a lot, you should be going all the way and properly creating classes...
I can't think of a good specific example, i've mostly used them for small things, like temporary maps that need a single key but multiple pieces of information in the value...
I use them in place of private classes. The are great when used internally in a class.
Exposing them outside the class only led to confusion. I kept having to open the class to determine what was what.
What about on a login form? They see those all of the time.
var loginCredentials =
new Tuple<string, SecureString>(nameTextBox.Text, passwordTextBox.Text);
if (Login(loginCredentials))
Console.Writeline("Login - Success!");
else
Console.Writeline("Login - Failure");
...
public bool Login(Tuple<string, SecureString> loginCredentials)
{
return ...
}
Background
Currently, if I want to create a new object in C# or Java, I type something similar to the following:
List<int> listOfInts = new List<int>(); //C#
ArrayList<String> data = new ArrayList<String>(); //Java
C# 3.0 sought to improve conciseness by implementing the following compiler trick:
var listofInts = new List<int>();
Question
Since the compiler already knows that I want to create a new object of a certain type (By the fact that I'm instantiating it without assigning it a null reference or assigning a specific method to instantiate it), then why can't I do the following?
//default constructors with no parameters:
List<int> listOfInts = new(); //c#
ArrayList<String> data = new(); //Java
Follow Up Questions:
What are possible pitfalls of this approach. What edge cases could I be missing?
Would there be other ways to shorten instantiation (without using VB6-esque var) and still retain meaning?
NOTE: One of the main benefits I see in a feature like this is clarity. Let say var wasn't limited. To me it is useless, its going to get the assignment from the right, so why bother? New() to me actually shortens it an gives meaning. Its a new() whatever you declared, which to me would be clear and concise.
C# saves in the other end:
var listOfInts = new List<int>();
What edge cases could I be missing?
I briefly discussed this possible C# syntax on my blog in January. See the comments to that post for some reader feedback on the pros and cons of the syntax.
Would there be other ways to shorten instantiation (without using VB6-esque var) and still retain meaning?
Possibly, yes.
"var" in C#, however, is nothing like "variant" in VB6. "var" does not mean the same thing as "object", nor does it introduce dynamic typing or duck typing. It is simply a syntactic sugar for eliminating the redundant stating of the type of the right hand side.
In C# 3 there's already the mirror image for local variables, implicitly typing:
var listOfInts = new List<int>();
This doesn't work for non-local variables though.
In Java, type inference takes into the assignment target into account, so using static imports and cunning libraries such as the Google Java Collections you can write code such as:
List<Integer> integers = newArrayList();
Note that that keeps the variable interface-based while specifying the implementation in the construction side, which is nice.
In the new Java 7 proposals there's a type inference proposal, which will life easier re. generics declarations.
e.g.
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
vs
Map<String, List<String>> anagrams = new HashMap<>();
See here for more information.
In general when using object oriented approaches, you will often create more instances of a more specific type than your variable. Also, it is often a good idea to use a less specific type or an interface. In those cases, this would not make sense.
Think of interfaces:
IList<int> = new(); // What instance should the compiler infer?
Also, from a technical point of view, the signature of an operation does not include its return type, so that this kind of assignment would be completely different from the normal case.
Your version is less readable, sorry.
Code is meant to be read by humans, only incidentally by machines.
I agree that would be a nice feature. A better example would be where even more typing is required:
Dictionary<string, int> myDictionary = new Dictionary<string, int>();
Life would be easier, albeit only slightly, if that could be instantiated as:
Dictionary<string, int> myDictionary = new();
and:
Dictionary<string, int> myDictionary = { {"a",1}, {"b",2} };
C# has:
var listOfInts = new List<int>();
which achieves kind of the same thing.
C# 3.0 has a mechanism to reduce the duplication in typing, but it is done by being vague about the type you're declaring, but explicit in the type you are constructing:
e.g.
var listOfInts = new List<int>();
In C#, there's
var listOfInts = new List<int>();
in C#, theres already something like this namely:
var listOfInts = new List<int>();
In Java this doesn't make too much sense, as you will usually declare variables with the interface type:
List<String> myList = new ArrayList<String>();
It would, however, in most cases make sense to be able to omit the declaration of the generic type without compiler warnings, such as:
List<String> myList = new ArrayList();
But as Java is always very explicit and verbose about everything, this might as well stay the same.
(And why again would anyone code C# or Java without an IDE?)
EDIT:
Oh, there's a proposal for that! Sweet. Thanks, Brian.
Java has
List<String> data = newList(); //Java, where newList() is a helper method to create an ArrayList();
List<String> data = newList("Hello", "World"); // a helper method which takes a T....
Map<String, List<String>> anagrams = newMap(); // Java, where newMap creates a new HashMap();
Code is read from left to right (if your language is not right to left).
That means that
var someTypeWithALongName = new TypeWithALongName<TypeParamOne,TypeParamTwo>();
puts important data to the right part (actual method / type constructor that is used to init variable, from which a reader of the code can infer knowledge about actual var type), which is less convenient to eye, compared to when it is located in the left.
What author suggests however is much better for a left to right reading human - we declare a variable of known type (not some unknown var type)
TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();
now important data (actual type that variable will have) is to the left, we can scan code on left side and notice actual types, not a fence of var declarations
var x = ....;
var y = ....;
var z = ....;
var xy = ....;
Code Complete book states that readability is the most important, and I find it hard to disagree with that. Saving 5(or less) seconds and using var instead of real type easily makes code review in future harder, can make code unreadable depending on the right part, and can plant unexpected errors that will be very hard to notice. All with the value of.. saving 5 seconds and not writing a declaring type for variable?
It is now a common knowledge that actual code writing is not taking that much time out of whole time consumed for program creation,especially if it is a product program) ( which usually has debugging, system testing, components integration, design, meetings, etc taking MUCH more time that actual code writing)
On other hand when we type
TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();
I find it hard not to interpret that line as anything but calling a default constructor for type and creating an instance of the type.
Also in case of wall of initializations we get actual type names on the beginning of the line, so its easy to scan code from top to bottom and we don't have to move eyes to the end of string to know what actually this concrete var initialization does.( And if you think scanning line to end is a free roll task , first of all its not, and with var its not just scanning, its also checking whether there is a bug in the right part of initialization (for example method with different return type is called or some other types of bugs which var allows))
TypeWithALongName<TypeParamOne,TypeParamTwo> someTypeWithALongName = new();
AnotherTypeWithLongNname someAnotherTypeWithLongNname = new();
List<int> idList = new();
Dictionary<int,string> lookupDict = new ();
I am against var use except for cases it was created for (anonymous types , generally coming from LINQ), and if we were to save up some space in a code I would prefer any code reducing strategies were happening on the right side.
I also believe that using var to declare a variable and assigning it to a return value of some method highly complicates code analysis and often introduces hard to catch bugs, that would have been completely avoided if var wasn't possible for such cases, so if only the constructors code could be shortened to a new() or new(ParamType param) and not some other method like
var x = someTypeLocalIstance.ComputeResults()
readability will only win once more.
I think Microsoft made it this way: a) var xy = new MyClass();
instead of this way: b) MyClass xy = new();
because a) is capable to hold anonymous classes and with b) that would not be possible.