How it works
An interface states which members a consumer may call. The loop holds ILabel references, so it knows that every item supplies Text even though the concrete implementations differ. ProductLabel stores a code, while CountLabel computes text from a number. The consumer does not need a switch over their runtime types. This makes adding another implementation possible without rewriting the printing loop.
Keep interfaces focused on what their consumers actually need. An interface with many unrelated members creates more obligations for every implementation and can conceal the smaller roles that would be easier to test and understand.
Add another record implementing ILabel and insert it into the array. Verify the loop needs no changes, then describe a member that would not belong in this small contract.
A working example
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
ILabel[] labels = { new ProductLabel("A7"), new CountLabel(3) };
foreach (var label in labels) Console.WriteLine(label.Text);
interface ILabel { string Text { get; } }
record ProductLabel(string Text) : ILabel;
record CountLabel(int Count) : ILabel { public string Text => $"count:{Count}"; }
Expected output
A7 count:3
Depend on the operation the consumer needs.