WebHU - Programozási kérdések és válaszok

A delegálthoz rendelt általános módszer

Kicsit tanácstalan voltam a küldöttekkel és az általános módszerekkel.

Lehet-e delegált hozzárendelni egy metódushoz általános típusparaméterrel?

I.E:

//This doesn't allow me to pass a generic parameter with the delegate.
public delegate void GenericDelegate<T>() 

someDelegate = GenericMethod;
public void GenericMethod<T>() where T : ISomeClass
{

}

Megpróbálom átadni ezt a delegált a függvénynek a metódus által várt interfész általános típusával, egy ehhez hasonló funkcióval:

void CheckDelegate(GenericDelegate<ISomeClass> mechanism);

így használhatom a delegált:

someDelegate<ImplementsSomeClass>();

  • Hogy néz ki someDelegate? (és milyen hibát kapsz?) 08.12.2013
  • public delegate void GenericDelegate‹in T›(); 08.12.2013
  • msdn.microsoft.com/en-us/library/sx2bwtw7.aspx 08.12.2013
  • A 'someDelegate' változó nem használható típusargumentumokkal. 08.12.2013
  • Még mindig nem találtam rá módot erre. Az elmúlt két napban kísérleteztem. BOUNTY MÓD? 11.12.2013
  • Nekem úgy hangzik, mintha egy nyitott funkciót szeretne hozzárendelni egy zárt küldötthez, vagy egy zárt funkciót egy nyitott delegálthoz. Meg tudnád fogalmazni pontosabban, hogy mit szeretnél csinálni? 11.12.2013
  • Egy olyan funkciót delegálok, amely megváltoztathatja egy objektum állapotát. Az általam delegált függvény egy ‹U› típusú paramétert vesz fel, ahol U : ISomeState. Ezután beadom a delegált egy másik objektumba, amely azt fogja használni az állapot manipulálására, amikor megváltoztatja állapotát. (Megjegyzendő, hogy ezt beírva nem tudtam segíteni, de éreztem, hogy egy nagy nem-nem jön felém) 11.12.2013
  • A CheckDelegatefüggvény void CheckDelegate(SomeDelegate<ISomeClass> mechanism){} vagy void CheckDelegate(GenericDelegate<ISomeClass> mechanism){}ként van meghatározva? Ez két teljesen különböző dolog. 11.12.2013
  • miért nem használja a delegate-t az ISomeState típusú paraméterrel? 11.12.2013
  • Javítva YK1, a módosított kód fent van. 11.12.2013
  • Melyik .NET verziót célozza meg? 11.12.2013
  • Célom a .NET 4.5 11.12.2013

Válaszok:


1

A kérdésnek nincs értelme, mert soha nem használhat nyílt általános típust a tárolási hely deklarálására (például helyi változó vagy mező). Mindig zárva kell lennie.

Úgy tudom, hogy egy GenericDelegate<T>-et szeretne átadni egy ilyen értéket argumentumként használó metódusnak. De még ekkor is a delegált típus zárttá válik, és az általános típusparaméter a T.

A mintakódodba írod

someDelegate = GenericMethod;

de milyen típusúnak kell lennie a someDelegate-nek? Nyilvánvalóan be kell zárni (GenericDelegate<string>), vagy le kell zárni egy általános típusparaméterrel a külső hatókörből:

void SomeOuterMethod<T>() where T : ISomeClass {
    GenericDelegate<T> someDelegate = GenericMethod<T>;
}

Remélem értettem a problémádat. Ha nem, kérem pontosítsa. Ha egy kicsit kifejti, hogymit szeretne elérni, megpróbálok praktikus megoldást javasolni.

Más nyelvek, például a Haskell, támogatják a nyílt általános típusok értékeinek átadását (más szóval, rendelkezhet egy IEnumerable<> típusú változóval). Ez szükséges a monádok megvalósításához. A CLR nem rendelkezik ezzel a funkcióval.


Új gondolat: delegált helyett létrehozhat egy nem általános alaptípust egy általános metódussal, amely felülbírálható:

interface CheckHandler {
 public void Check<T>(T someArg);
}

Remélhetőleg ez lefedi az Ön forgatókönyvét. Nem lehet szabadon elhaladni egyetlen CheckHandler mellett sem. A Check metódusa ezután tetszőleges típusú argumentummal hívható meg.

10.12.2013
  • Megpróbálom módosítani egy objektum állapotát. A T típus azt az állapotot jelöli ki, amelybe az objektumnak át kell térnie. 11.12.2013
  • Jó magyarázat arra, hogy a delegált miért nem nevezhető someDelegate<ClassThatImplementsSomeClass>();-nek. Teljesen egyetértek. 11.12.2013
  • Tehát lehetetlen, mert a típust zárttá alakítom át, amikor helyesen adom át az „ISomeClass”-nak? 11.12.2013
  • Azt hiszem. Ha meg akarja tartani az általánosságot, általános típusparamétereket kell hozzáadnia az összes metódushoz (vagy a környező típusokhoz), hogy a tényleges általános típus argumentumot az összes érintett kódon keresztül lehessen futtatni. Új ötletet adtam a válaszhoz. Ez segít? 11.12.2013
  • @usr: Úgy hangzik, mint amire gondoltam [lásd a válaszomat] 11.12.2013

  • 2

    Lehetséges egyetlen "dolog", amely több paramétertípuson is működhet, de a Delegate osztály erre nem alkalmas. Ehelyett meg kell határoznia egy interfészt. Egyszerű példaként:

    public interface IMunger<TConstraint>
    {
        void Munge<T>(ref T it) where T : TConstraint;
    }
    public class Cloner : IMunger<ICloneable>
    {
        public void Munge<T>(ref T it) where T : ICloneable
        {
            if (typeof(T).IsValueType) // See text
                return;
            it = (T)(it.Clone());
        }
    }
    

    Még akkor is, ha a rendszernek van egy előre definiált delegált típusa by-ref paraméterrel (így például a ActByRef<ICloneable> aláírása void Invoke(ref ICloneable p1) lenne), az ilyen delegált csak egy pontos ICloneable típusú változónál használható. Ezzel szemben a Cloner nem általános osztálytípus egyetlen objektuma olyan metódust tud biztosítani, amely alkalmas bármilyen tárolóhelytípushoz, amely megvalósítja a ICloneable elemet. Vegye figyelembe azt is, hogy ha a metódus egy ref értéket ad át egy olyan változónak, amely egy bekeretezett értéktípusú példányra hivatkozik, akkor lecseréli azt a példány másolatára való hivatkozásra, de ha egy ref értéket ad át egy értéktípusra. változót, úgy hagyja, ahogy van (kivéve, ha az értéktípus megtartja állapotát egy változtatható osztályobjektumban, amelyre hivatkozik – ez egy nagyon fura minta –, ha a StructType foo = (StructType)(bar.Clone()); csak foo = bar-nek felel meg; a struktúra típusa esetleg implementálja a ICloneable kódot, hogy részt vehessen egy mély klónozási hierarchiában, de ez nem jelenti azt, hogy a Clone metódusának bármit is kell tennie.

    10.12.2013

    3

    Frissítettük a példát, hogy támogassa a metódust paraméterként, amely csak azt mutatja be, hogyan hívható meg az általános delegáció más metódus paramétereként.

    class Program
    {
        public delegate T Transformer<T>(T arg) where T : IComparable;
    
        public static void Transform<T>(T value, Transformer<T> method) where T: IComparable
        {
            Console.WriteLine(method(value));
        }
    
        static void Main(string[] args)
        {
            Transform(5, Square);
        }
    
        static int Square(int x)
        {
            return x * x;
        }
    }
    
    10.12.2013

    4

    Kipróbáltam a következőket:

    public class Test
    {
        public interface ISomeClass { }
    
        public class ImplementsSomeClass : ISomeClass { }
    
        public delegate void GenericDelegate<T>() where T : ISomeClass;
    
        public void GenericMethod<T>() 
        {
            // EDIT: returns typeof(ImplementsSomeClass)
            var t = typeof(T); 
        }
    
        public void CheckDelegate(GenericDelegate<ISomeClass> mechanism)
        {
            // EDIT: call without generic argument since it is already determined 
            mechanism(); 
        }
    
        public void test()
        {
            GenericDelegate<ISomeClass> someDelegate = GenericMethod<ImplementsSomeClass>;
            CheckDelegate(someDelegate);
        }
    }
    

    És nincs fordítási hibám. Ez futásidejű probléma, vagy félreértettem a probléma leírását?

    10.12.2013
  • Meg akarom hívni a delegált az általános paraméterrel. 11.12.2013
  • someDelegate‹ClassThatImplementsSomeClass›(); 11.12.2013
  • Megtehető-e anélkül, hogy minden alkalommal létrehozna egy delegált? Szeretnék mélyebben megérteni, hogy miért nem hívhatók meg a küldöttek általános paraméterekkel. A delegált meghívja a someDelegate‹SomeClassImplementation›(); tényleg az, amit keresek. 11.12.2013
  • @10001110101 Ezt nem teheti meg, mivel az átadott delegáltnak be van állítva az általános paramétere, mert someDelegate = GenericMethod<ImplementsSomeClass>;-ként definiáltuk, utólag nem hívhatja meg más paraméterrel. Erről bővebben lásd az usr válaszát. 11.12.2013
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..