0

This ties in a lot to questions like How to add a range of items to an IList?, where some of the answers might be useful. However, I'm interested in an actual usecase and how the maintainers intend for the SDK to be used in the right way.

I am trying to create a virtual network using the azure-sdk-for-net.

The sample works with hardcoded array expression initializers, but I have data arriving from some other source and need to construct VirtualNetworkData from that incoming data.

As far as I have seen, this is an issue with all lists in the SDK.

This is what the sample does:

var data = new VirtualNetworkData
{
    DhcpOptionsDnsServers = { "1", "2" }
}

From what I can decipher, this syntax somehow calls the Add method on the IList interface.

This approach won't work for me, as I have data that I need to build and manage on the fly.

This is not allowed, since DhcpOptionsDnsServers only exposes a getter:

var myDnsServers = new List<string> { "1", "2" };
var data = new VirtualNetworkData
{
    // CS0200: Property or indexer 'VirtualNetworkData.DhcpOptionsDnsServers' cannot be assigned to -- it is read only
    DhcpOptionsDnsServers = myDnsServers
}

This error gave me the (probably bad) idea to extend the interface backing this property:

var myDnsServers = new List<string> { "1", "2" };
var data = new VirtualNetworkData
{
    // CS1503: Argument 1: cannot convert from 'string[]' to 'string'
    DhcpOptionsDnsServers = { myDnsServers.ToArray() }
};

With this extension, the above works but it feels like I violate all sorts of best practices.

internal static class CollectionExtension
{
    public static void Add(this ICollection<string> list, string[] range)
    {
        range.ToList().ForEach(r => list.Add(r));
    }
}

And lastly, one option is this:

var myDnsServers = new List<string> { "1", "2" };
var data = new VirtualNetworkData();
myDnsServers.ForEach(dns => data.DhcpOptionsDnsServers.Add(dns));

// Or concat
data.DhcpOptionsDnsServers.concat(myDnsServers);

I don't particularly like any of the options, but how I am supposed to work with the SDK and lists properly?

jokarl
  • 1,913
  • 2
  • 24
  • 52
  • 1
    A simple foreach loop that calls the `Add` method. Simple and readable. A `ForEach` also works, but I (personal preference) generally prefer the simple loop as it is easier to interpret and debug. – NotFound Feb 28 '23 at 10:14

1 Answers1

1

In the Azure SDK for C#, some properties that expose lists, such as DhcpOptionsDnsServers in the VirtualNetworkData class, are designed to be read-only.

And you cannot assign a new list to them but can only add elements to the existing list. This helps to prevent overwrites of important configuration data.

To work with such read-only lists, you can add elements to the existing list using the Add method, as you have already shown in your last example:

var myDnsServers = new List<string> { "1", "2" };
var data = new VirtualNetworkData();
myDnsServers.ForEach(dns => data.DhcpOptionsDnsServers.Add(dns));

And also you can use the Concat method to add elements from another list to the existing list

var myDnsServers = new List<string> { "1", "2" };
var data = new VirtualNetworkData();
data.DhcpOptionsDnsServers = data.DhcpOptionsDnsServers.Concat(myDnsServers).ToList();

Both of these approaches are safe to use, as they work with the intended behaviour of the SDK and ensure that you do not accidentally overwrite existing configuration data.

Rajesh Mopati
  • 1,329
  • 1
  • 2
  • 7
  • Thanks for the response! But wouldn't using `IReadOnlyList` and allowing `init` achieve the same thing but it would be easier to create the object? – jokarl Feb 28 '23 at 11:04
  • 1
    Yes, that's correct! If the VirtualNetworkData class used IReadOnlyList instead of IList for the DhcpOptionsDnsServers property, and marked it with the init keyword, you would be able to assign the list on initialization but not modify it afterwards. – Rajesh Mopati Feb 28 '23 at 11:35
  • @jokarl not per se. If you assume all methods inherit from a `List` and remain that way then it could be implemented like that. But what if they use their own implementation of an `IList`, which they almost certainly did? An example could be a custom `Add` method that performs validation. – NotFound Feb 28 '23 at 12:28