This is a very interesting question :-)
The answer is pretty simple actually.
Although there is no boxing/unboxing involved when accessing elements of a generic list, there is a method call involved. The indexer is called on the list, which returns a "myStruct" variable. Because this is a value type, a copy will be returned, so updating the object will update the copy, and not the original item.
In the case of an array, accessing an element does not involve a method call. The element is accessed directly, so the Update() method will work on the original entry in the array, not a copy. This becomes clear when you look at the IL code generated:
For List<myStruct>:
ldloc.0
ldloc.1
callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<valuetype ConsoleApplication1.myStruct>::get_Item(int32)
stloc.3
ldloca.s CS$0$0000
ldloc.1
For myStruct[]:
ldloc.0
ldloc.2
ldelema ConsoleApplication1.myStruct
ldloc.2