▁using ▁the ▁. ▁method ▁on ▁the ▁elements . ▁The ▁implementation ▁does ▁not ▁depend ▁on ▁the ▁exact ▁type ▁of ▁element ▁stored ▁in ▁the ▁array , ▁so ▁it ▁should ▁be ▁possible ▁to ▁write ▁a ▁single ▁function ▁that ▁works ▁on ▁all ▁types ▁of ▁arrays . ▁It ▁is ▁easy ▁to ▁implement ▁functions ▁of ▁type : ▁ ▁boolean ▁equal Array s ( Object [] ▁a 1 , ▁Object [] ▁a 2 ); ▁void ▁sh uffle Array ( Object [] ▁a ); ▁ ▁However , ▁if ▁array ▁types ▁were ▁treated ▁as ▁invariant , ▁it ▁would ▁only ▁be ▁possible ▁to ▁call ▁these ▁functions ▁on ▁an ▁array ▁of ▁exactly ▁the ▁type ▁. ▁One ▁could ▁not , ▁for ▁example , ▁sh uffle ▁an ▁array ▁of ▁strings . ▁ ▁Therefore , ▁both ▁Java ▁and ▁C # ▁treat ▁array ▁types ▁cov ari antly . ▁For ▁instance , ▁in ▁Java ▁ ▁is ▁a ▁sub type ▁of ▁, ▁and ▁in ▁C # ▁ ▁is ▁a ▁sub type ▁of ▁. ▁ ▁As ▁discussed ▁above , ▁cov ari ant ▁arrays ▁lead ▁to ▁problems ▁with ▁writes ▁into ▁the ▁array . ▁Java ▁and ▁C # ▁deal ▁with ▁this ▁by ▁mark ing ▁each ▁array ▁object ▁with ▁a ▁type ▁when ▁it ▁is ▁created . ▁Each ▁time ▁a ▁value ▁is ▁stored ▁into ▁an ▁array , ▁the ▁execution ▁environment ▁will ▁check ▁that ▁the ▁run - time ▁type ▁of ▁the ▁value ▁is ▁equal ▁to ▁the ▁run - time ▁type ▁of ▁the ▁array . ▁If ▁there ▁is ▁a ▁mismatch , ▁an ▁ ▁( Java ) ▁or ▁ ▁( C # ) ▁is ▁thrown : ▁ ▁//