0

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]))
        });
  1. Why doesn't c# allow this? I think it should. I think converting legacy code to c# should be as painless as possible.
  2. Is there a better way that I get around this and still use the object initializer?
sstan
  • 35,425
  • 6
  • 48
  • 66
toddmo
  • 20,682
  • 14
  • 97
  • 107
  • 1
    Take a look at this post: http://stackoverflow.com/questions/601153/missing-the-with-keyword-in-c-sharp – David Tansey Aug 06 '16 at 23:02
  • 2
    @DavidTansey that's not the same `With`. the one you linked is [that one](https://msdn.microsoft.com/en-us/library/wc500chb.aspx) but the one in the question is [this one](https://msdn.microsoft.com/en-us/library/bb385125.aspx) – Sehnsucht Aug 06 '16 at 23:06
  • Questions of the type "Why doesn't language X have feature Y?" rarely yield satisfactory answers. Maybe this was considered and rejected for any number of reasons including "It's nice, but we don't have time to implement this." See Eric Lippert's asides in this [meta question](http://meta.stackexchange.com/q/96310/233306). – Mike Zboray Aug 06 '16 at 23:08
  • Get these values in your query with a let expression. Better still, don't use reflection. – Matthew Whited Aug 06 '16 at 23:15

1 Answers1

3

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.

sstan
  • 35,425
  • 6
  • 48
  • 66
  • It's also worth calling attention to the fact that for an object initializer expression, a C# compiler will generate a temporary variable. The expression itself is atomic; it is either complete or unavailable to the program. For example, `var c = new SomeClass { X = 1, Y = 2 }; c = new SomeClass { X = 3, Y = c.X };` is legal; `c.X` here is 1 because at the moment when it is being evaluated, `c` still holds the old value! – ach Aug 07 '16 at 03:40
  • It is actually not necessarily true that C# 'eliminates all dependencies on the order of property initialization'. To me, that's a bad style of programming, but still possible: property setters may produce different side effects when called in different order. – ach Aug 07 '16 at 03:49
  • Great answer, but I disagree in one thing, that "limitation" does not mean that is violating the DRY principle. DRY principle goes beyond. It is more to it than that. Whether in code, architecture, requirements documents, or user documentation, duplication of knowledge - not just text - is the real culprit. -- [DRY](http://c2.com/cgi/wiki?DontRepeatYourself) – jherax Aug 07 '16 at 04:34
  • Thanks for helping me dry out my code. But, saying that the languages are (or should be) completely independent is not correct in my opinion because they are related, both being members of the .Net product line. If you made your comment about Python and Java, I'd totally agree with you. But given that all .Net languages compile to CIL, they should all round trip to one another, IMHO. This would allow developers to pick the language from a dropdown in the IDE, for example. Then, the concept of legacy becomes moot. There would be no legacy; just .Net and the power of choice. – toddmo Aug 07 '16 at 21:41