Repository: dotnet/runtime
File: src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs (C#)

Code before:
        {
            uint sizeLength = DwarfHelper.SizeOfULEB128((ulong)_types.Length);
            return (int)(sizeLength + (uint)_types.Length);
        }

        public int Encode(Span<byte> buffer)
        {
            DwarfHelper.WriteULEB128(buffer, (ulong)_types.Length);
            uint sizeLength = DwarfHelper.SizeOfULEB128((ulong)_types.Length);
            for (int i = 0; i < _types.Length; i++)
            {
                buffer[(int)sizeLength + i] = (byte)_types[i];
            }
            return (int)(sizeLength + (uint)_types.Length);
        }
    }

    public static class WasmResultTypeExtensions
    {
        public static string ToTypeListString(this WasmResultType result)
        {
            var types = result.Types.ToArray();

            if (types == null || types.Length == 0)
                return string.Empty;

            return string.Join(" ", types.Select(t => WasmValueTypeExtensions.ToString(t)));
        }
    }

    public struct WasmFuncType : IEquatable<WasmFuncType>
    {
        private readonly WasmResultType _params;
        private readonly WasmResultType _returns;

        public WasmFuncType(WasmResultType paramTypes, WasmResultType returnTypes)
        {
            _params = paramTypes;
            _returns = returnTypes;
        }

        public readonly byte[] Encode()
        {
            int totalSize = 1+_params.EncodeSize() + _returns.EncodeSize();
            byte[] buffer = new byte[totalSize];
            buffer[0] = 0x60; // function type indicator

            var span = buffer.AsSpan();

            int paramSize = _params.Encode(span.Slice(1));
            int returnSize = _returns.Encode(span.Slice(1+paramSize));

Review comment (bug):
I think this is all unnecessary if I'm not wrong about how `Join(string, IEnumerable)` is implemented. And the Array->Span->Array roundtrip feels superfluous and avoidable.

Code after:
                return 0;

            int code = _types[0].GetHashCode();
            for (int i = 1; i < _types.Length; i++)
            {
                code = HashCode.Combine(code, _types[i].GetHashCode());
            }

            return code;
        }

        public int EncodeSize()
        {
            uint sizeLength = DwarfHelper.SizeOfULEB128((ulong)_types.Length);
            return (int)(sizeLength + (uint)_types.Length);
        }

        public int Encode(Span<byte> buffer)
        {
            int sizeLength = DwarfHelper.WriteULEB128(buffer, (ulong)_types.Length);
            Span<byte> rest = buffer.Slice(sizeLength);
            for (int i = 0; i < _types.Length; i++)
            {
                rest[i] = (byte)_types[i];
            }
            return (int)(sizeLength + (uint)_types.Length);
        }
    }

    public static class WasmResultTypeExtensions
    {
        public static string ToTypeListString(this WasmResultType result)
        {
            return string.Join(" ", result.Types.ToArray().Select(t => t.ToTypeString()));
        }
    }

    public struct WasmFuncType : IEquatable<WasmFuncType>
    {
        private readonly WasmResultType _params;
        private readonly WasmResultType _returns;

        public WasmFuncType(WasmResultType paramTypes, WasmResultType returnTypes)
        {
            _params = paramTypes;
            _returns = returnTypes;
        }

        public readonly int EncodeSize()
        {
            return 1 + _params.EncodeSize() + _returns.EncodeSize();