C # Bağımsız Değişken İşlevi


141

C # 'da sayısal bir ayrım yapan bir işlev yazdım. Şöyle görünüyor:

public double Diff(double x)
{
    double h = 0.0000001;

    return (Function(x + h) - Function(x)) / h;
}

Ben herhangi bir işlevi, mümkün olduğu gibi geçmek mümkün olmak istiyorum:

public double Diff(double x, function f)
{
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

Bence bu delegelerle mümkün olabilir (belki?) Ama onları nasıl kullanacağımdan emin değilim.

Herhangi bir yardım büyük mutluluk duyacağız.

Yanıtlar:


146

Func'un yukarıda belirtildiği gibi kullanılması işe yarıyor ancak aynı görevi yapan ve aynı zamanda adlandırmada niyeti tanımlayan delegeler de var:

public delegate double MyFunction(double x);

public double Diff(double x, MyFunction f)
{
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

public double MyFunctionMethod(double x)
{
    // Can add more complicated logic here
    return x + 10;
}

public void Client()
{
    double result = Diff(1.234, x => x * 456.1234);
    double secondResult = Diff(2.345, MyFunctionMethod);
}

5
3.5 ve sonrasında Func <delegeleri ve delegeler birbirinin yerine kullanılabilir ve bu da anonim delegeler ve lambdaların (anonim delegeler için sözdizimsel şeker olan) da kullanılabileceği anlamına gelir. Bu nedenle, parametreyi Func <double, double> ya da double alan ve double döndüren bir temsilci olarak belirtmeniz önemli değildir. Adlandırılmış bir temsilcinin size sağladığı tek gerçek avantaj xml-doc yorumları ekleme yeteneğidir; tanımlayıcı adların türü yerine parametre adı kadar uygulanması kolaydır.
KeithS

3
Yöntem prototipinin hala Func <x, y> kodundan daha okunabilir hale getirdiğini iddia ediyorum - sadece kodu okunabilir yapan adlandırma değil ve söylediğiniz gibi lambdaları koda geçirmenizi engellemiyor.
Ian Johnson

Delege türünün adlandırılması netliği kodlamak için çok önemliyse, çoğu durumda bir arayüze ve uygulamalara yöneleceğim.
quentin-starin

@ qstarin, yalnızca temsilci adlandırma değil, yöntemin alması gereken bağımsız değişkenlerin adlandırılmasıdır, özellikle de yalnızca yerel türdeyse. Haklısın, çoğunlukla delegeler üzerinden arayüzler kullanıyorum
Ian Johnson

Bunlardan birini ortak işlevsellik sağlayan ortak bir işlev olarak yapıyorsam (çok yaygın olmayan bir dönüş türüyle), void ile kullanmaya çalışana kadar her şey çalışır. Gerçekten Func yerine Action kullanarak yinelenen bir işlev yapmam gerekiyor mu yoksa daha iyi bir yol var mı?
Dan Chase

175

.Net'te (v2 ve üstü) delegeler olarak geçiş işlevlerini çok kolaylaştıran birkaç genel tür vardır.

Dönüş türlerine sahip işlevler için Func <> ve dönüş türlerine sahip olmayan işlevler için Eylem <> vardır.

Hem Func hem de Action öğesinin 0 ila 4 parametre aldığı bildirilebilir. Örneğin, Func <double, int> parametre olarak bir double alır ve bir int döndürür. <Double, double, double> eylemi, parametre olarak üç katına çıkar ve hiçbir şey döndürmez (geçersiz).

Böylece Diff işlevinizi bir Func almak için bildirebilirsiniz:

public double Diff(double x, Func<double, double> f) {
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

Ve sonra böyle adlandırın, sadece Func veya Action'inizin imzasına uyan işlevin adını verin:

double result = Diff(myValue, Function);

Fonksiyonu lambda sözdizimi ile hatta yazabilirsiniz:

double result = Diff(myValue, d => Math.Sqrt(d * 3.14));

29
.NET 4, her iki Funcve Actionizin vermek için güncellendi 16 kadar parametreleri.
Joel Mueller

5
Yapılması gerçekten harika bir şey Func<double, double>, elbette sayısal olarak hesaplanan giriş fonksiyonunun ilk türevi olanı döndürmek olacaktır . Giriş işlevinin türevini return x => (f(x + h) - f(x)) / h;döndüren bir aşırı yük bile yazabilirsiniz n.
Ani

15
public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}

Kullanımı:

var ReturnValue = Runner(() => GetUser(99));

Merak ediyorum, neden genel tip parametresi?
kdbanman

2
Bu hatayı alıyorum: 'Runner <T> (Func <T>)' yöntemi için tür bağımsız değişkenleri kullanımdan çıkarılamaz. Tür bağımsız değişkenlerini açıkça belirtmeyi deneyin.
DermFransızca

"FuncToRun" yöntem imzanız nedir?
kravits88
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.