Varianssi (in/out) rajapinnoissa ja delegaateissa
Perehtykää C#:n varianssiin: out tuottajille (kovarianssi) ja in kuluttajille (kontravarianssi) rajapinnoissa ja delegaateissa.
Varianssi (in/out) rajapinnoissa ja delegaateissa on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/3. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C# Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C# Academy-kurssilla on yhteensä 3 oppituntia.
Varianssin yleiskatsaus
Varianssin ansiosta geneeriset rajapinnat ja delegaatit voivat toimia perintähierarkian kanssa.
- out = kovarianssi (tuottaja)
- in = kontravarianssi (kuluttaja)
- Turvallista, kun API tuottaa tai kuluttaa ainoastaan tyyppiä T
Kovarianssiesimerkki
IEnumerable<out T> on kovariantti: kissojen jonoa voidaan käyttää siellä, missä odotetaan eläinten jonoa.
using System;
using System.Collections.Generic;
public class Animal { public virtual string Name() { return "animal"; } }
public class Cat : Animal { public override string Name() { return "cat"; } }
public class Program
{
static void PrintAll(IEnumerable<Animal> animals)
{
foreach (Animal a in animals)
{
Console.WriteLine(a.Name());
}
}
public static void Main(string[] args)
{
List<Cat> cats = new List<Cat>();
cats.Add(new Cat());
// IEnumerable<Cat> -> IEnumerable<Animal> is allowed (out T)
PrintAll(cats);
}
}
Kontravarianssiesimerkki
IComparer<in T> on kontravariantti: Animal-vertailija toimii myös Cat-tyypin kanssa, koska se vain kuluttaa T:tä.
using System;
using System.Collections.Generic;
public class Animal { public string N; public Animal(string n){ N=n; } }
public class Cat : Animal { public Cat(string n) : base(n) {} }
// Comparer can compare any Animals
public class AnimalNameComparer : IComparer<Animal>
{
public int Compare(Animal x, Animal y)
{
return string.Compare(x == null ? "" : x.N, y == null ? "" : y.N, StringComparison.Ordinal);
}
}
public class Program
{
public static void Main(string[] args)
{
List<Cat> cats = new List<Cat>();
cats.Add(new Cat("Miso"));
cats.Add(new Cat("Ada"));
// IComparer<Animal> can be used as IComparer<Cat> (in T)
cats.Sort(new AnimalNameComparer());
foreach (Cat c in cats) Console.WriteLine(c.N);
}
}
Delegaattien varianssi
Delegaatit ovat myös variantteja: Func<out TResult> (tuottaja) ja Action<in T> (kuluttaja).
using System;
public class Animal { public virtual string Speak(){ return "???"; } }
public class Cat : Animal { public override string Speak(){ return "meow"; } }
public class Program
{
static Animal MakeAnimal() { return new Animal(); }
static void HandleAnimal(Animal a) { Console.WriteLine(a.Speak()); }
public static void Main(string[] args)
{
// Func<Cat> can be used where Func<Animal> is expected? Yes, because TResult is out.
Func<Animal> maker = new Func<Cat>(delegate { return new Cat(); });
Console.WriteLine(maker().Speak());
// Action<Animal> can be used where Action<Cat> is expected? Yes, because T is in.
Action<Cat> catSink = new Action<Animal>(HandleAnimal);
catSink(new Cat());
}
}
Mukautetut variantit rajapinnat
Suunnittelusääntö: merkitkää vain tuottamiseen käytettävät parametrit out-merkinnällä ja vain kuluttamiseen käytettävät parametrit in-merkinnällä turvallisten muunnosten mahdollistamiseksi.
using System;
// Producer-only interface: out T
public interface ISource<out T>
{
T Get();
}
// Consumer-only interface: in T
public interface ISink<in T>
{
void Put(T item);
}
public class Animal { public string N; }
public class Cat : Animal { }
public class CatSource : ISource<Cat>
{
public Cat Get() { return new Cat(); }
}
public class AnimalSink : ISink<Animal>
{
public void Put(Animal a) { Console.WriteLine("Got animal"); }
}
public class Program
{
public static void Main(string[] args)
{
ISource<Animal> animals = new CatSource(); // out T allows upcast
ISink<Cat> cats = new AnimalSink(); // in T allows down-assign
animals.Get();
cats.Put(new Cat());
}
}
Varianssivinkit
Vinkit:
- out-parametreja saa käyttää vain tulospaikoissa (palautustyypeissä ja kovarianssia tukevissa kohdissa).
- in-parametreja saa käyttää vain syötepaikoissa (metodien parametreina).
- Älkää yhdistäkö saman T-tyypin tuottamista ja kuluttamista varianssia määritettäessä.
- Varianssi koskee rajapintoja ja delegaatteja, ei luokkia.
Kovarianssin avainsana
Kertaus
Kertaus: Käyttäkää rajapinnoissa ja delegaateissa tuottajille out-merkintää (kovarianssi) ja kuluttajille in-merkintää (kontravarianssi). Pitäkää API:t yksisuuntaisina turvallisten muunnosten mahdollistamiseksi.
Opi C# tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 93
- Oppitunnit
- 346
Usein kysytyt kysymykset
Onko oppitunti ”Varianssi (in/out) rajapinnoissa ja delegaateissa” ilmainen?
Kyllä – oppitunnin ”Varianssi (in/out) rajapinnoissa ja delegaateissa” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C# Academy-kurssin, päivitä CoddyKit PROhon. C# Academy-kurssilla on yhteensä 3 oppituntia.
Mitä opin oppitunnilla ”Varianssi (in/out) rajapinnoissa ja delegaateissa”?
Perehtykää C#:n varianssiin: out tuottajille (kovarianssi) ja in kuluttajille (kontravarianssi) rajapinnoissa ja delegaateissa. Harjoittelet C# Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni C# Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin C# Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/3.
Kuinka kauan ”Varianssi (in/out) rajapinnoissa ja delegaateissa”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä C# Academy-oppitunnilla?
Kyllä. Jokainen C# Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Geneeriset metodit ja tyypit sekä rajoitteet
- Varianssi (in/out) rajapinnoissa ja delegaateissa
- Nullable-viitetyypit (perustiedot) ja annotaatiot (C# 6 -mallit)