Skip to content

Enumerable.Empty<T> isn't serializable using the DataContractSerializer #724

@PhilPJL

Description

@PhilPJL

It's common/best/good practise to use Enumerable.Empty() to avoid unnecessary allocations, so we have a lot of code like this to ensure properties aren't serialized as null:

[DataContract]
public class Test
{
	public Test()
	{
		Ints = Enumerable.Empty<int>();
	}
	
	[DataMember] public IEnumerable<int> Ints{ get; set; }
}

This works fine on the .NET framework when these DTOs are serialized using the DataContractSerializer (with WCF for instance).

On .NET Core 3.1.100 we now get

InvalidDataContractException: Type 'System.Linq.EmptyPartition`1[System.Int32]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.

We can successfully use

Array.Empty<T>()
new T [0]
new List<T>()

but Enumerable.Empty() should work as well.

Also, Enumerable.Empty is not serializable using the DataContractSerializer but is serializable using the DataContractJsonSerializer.

Complete example using LinqPad

void Main()
{
	Serializer.SerializeAsXml(new Test()).Dump();
}

[DataContract]
public class Test
{
	public Test()
	{
		Ints = Enumerable.Empty<int>();
	}
	
	[DataMember] public IEnumerable<int> Ints { get; set; }
}

// Define other methods, classes and namespaces here
public static class Serializer
{
	#region Xml serializer

	private static readonly XmlWriterSettings Settings =
		new XmlWriterSettings
		{
			Indent = true,
			OmitXmlDeclaration = true
		};

	[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times",
		Justification = "Code analysis is wrong")]
	public static string SerializeAsXml<T>(T theObject)
	{
		var serializer = new DataContractSerializer(typeof(T));
		var sb = new StringBuilder();

		using (var writer = new StringWriter(sb, CultureInfo.InvariantCulture))
		using (var stream = XmlWriter.Create(writer, Settings))
		{
			serializer.WriteObject(stream, theObject);
		}

		return sb.ToString();
	}

	#endregion
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions