Question

Comment puis-je implémenter mon propre mécanisme d'exécution différée en C #?

Ainsi, par exemple, j'ai:

string x = DoFoo();

Est-il possible d'effectuer certaines tâches magiques pour que DoFoo ne s'exécute pas avant que je & "utilise &"; x?

Était-ce utile?

La solution

Vous pouvez utiliser lambdas / délégués:

Func<string> doit = () => DoFoo();
//  - or -
Func<string> doit = DoFoo;

Vous pouvez ensuite appeler doit comme une méthode:

string x = doit();

Je pense que le plus proche que vous puissiez obtenir est quelque chose comme ceci:

Lazy<string> x = DoFoo;

string y = x; // "use" x

Avec une définition de Lazy<T> similaire à celle-ci (non testée):

public class Lazy<T>
{
    private readonly Func<T> func;
    private bool hasValue;
    private T value;

    public Lazy(Func<T> func)
    {
        this.func = func;
        this.hasValue = false;
    }

    public static implicit operator Lazy<T>(Func<T> func)
    {
        return new Lazy<T>(func);
    }

    public static implicit operator T(Lazy<T> lazy)
    {
        if (!lazy.hasValue)
        {
            lazy.value = lazy.func();
            lazy.hasValue = true;
        }
        return lazy.value;
    }
}

Malheureusement, il semble que les algorithmes d'inférence de type du compilateur ne puissent pas déduire automatiquement le type de Func<T> et ne puissent donc pas le faire correspondre à l'opérateur de conversion implicite. Nous devons déclarer explicitement le type du délégué, ce qui rend les instructions d'affectation plus détaillées:

// none of these will compile...
Lazy<string> x = DoFoo;
Lazy<string> y = () => DoFoo();
Lazy<string> z = delegate() { return DoFoo(); };

// these all work...
Lazy<string> a = (Func<string>)DoFoo;
Lazy<string> b = (Func<string>)(() => DoFoo());
Lazy<string> c = new Func<string>(DoFoo);
Lazy<string> d = new Func<string>(() => DoFoo());
Lazy<string> e = new Lazy<string>(DoFoo);
Lazy<string> f = new Lazy<string>(() => DoFoo);

Autres conseils

Une option consiste à utiliser la classe Lazy<T>, qui appartenait auparavant à la bibliothèque d’extensions parallèles et qui fait désormais partie du .Net Framework 4.0.

Il vous permet de retarder le traitement des données en fonction des threads.

Même s’il est un peu sale, vous pouvez toujours utiliser le mot-clé rendement:

public IEnumerable<int> DoFoo() {
   Console.WriteLine("doing foo");
   yield return 10;
}

[Test]
public void TestMethod()
{
    var x = DoFoo();
    Console.WriteLine("foo aquired?");
    Console.WriteLine(x.First());
}

Au lieu de passer une chaîne x , transmettez un délégué qui vous fournit une chaîne

Func<String> fooFunc=()=>DoFoo();

Pourquoi ne pas simplement appeler DoFoo () tant que vous ne le souhaitez pas?

- Modifier

Je veux dire, que voulez-vous dire & "utiliser &";

Par exemple, si vous souhaitez qu'il soit appelé lorsque '.ToString ()' est appelé, vous pouvez toujours hériter de la classe et implémenter votre fonction à cet endroit (mais cela ne serait pas très intuitif à mon humble avis).

Vous décrivez à peu près LINQ en action. Une requête linq décrit comment obtenir les données, mais les données sont récupérées (DoFunc est appelé) uniquement lorsque la requête est itérée. Déterminez si vous pouvez modifier votre conception pour accepter IQueryable<string> où vous avez besoin d'un string.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top