Bir dışlama argümanı açıkça nasıl reddedilir?


103

Bir arama yapıyorum:

myResult = MakeMyCall(inputParams, out messages);

ama aslında mesajlar umrumda değil. Eğer umursamadığım bir girdi parametresi olsaydı, sadece bir null geçirirdim. Geri dönüş olsaydı, umursamadığım bir şey olsaydı, onu bir kenara bırakırdım.

Bir çıkışa benzer bir şey yapmanın bir yolu var mı, yoksa daha sonra görmezden geleceğim bir değişken bildirmem gerekiyor mu?




Teşekkürler! En son sürümde olmaması ne yazık.
Andrew Ducker

Yanıtlar:


103

C # 7.0 ile başlayarak, parametreleri göz ardı etmenin yanı sıra önceden bildirmekten kaçınmak mümkündür.

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}

public void PrintXCoordinate(Point p)
{
    p.GetCoordinates(out int x, out _); // I only care about x
    WriteLine($"{x}");
}

Kaynak: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/


1
Maalesef bu, C # 7'ye dahil edilmemiştir (Nisan 2017 itibariyle).
tia

2
@tia. Cevabımı güncelledim. Görünüşe göre, arama karakteri değiştirildi *kadar _. Üzgünüm çok uzun sürdü.
Nolonar

14
out voidSözdizimi için kullanma fikirlerine bağlı kalmaları gerekirdi ve alt çizgi garip bir seçim gibi görünüyor.
David Anderson

1
@ DavidAnderson-DCOM Alt çizginin hayranı olmasam da, aşırı yük çözümü için tür adına ihtiyaçları olduğunu düşünüyorum.
Jonathan Allen

Hala bir parametre oluşturuyor gibi görünüyor, çünkü _ = {a value};herhangi bir derleme hatası olmadan fonksiyon çağrısından sonra satırı ekleyebilirim .
Bip901

37

Maalesef bir şeyi geçmek zorundasınız çünkü onu ayarlamak için metot gerekli. Bu yüzden gönderemezsiniz nullçünkü onu ayarlamak için gerekli olan yöntem patlayacaktır.

Çirkinliği gizlemeye yönelik bir yaklaşım, yöntemi outsizin için parametreyi böyle yapan başka bir yönteme sarmak olacaktır :

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

Daha sonra ihtiyacınız olmayan parametrelerle Other_MakeMyCalluğraşmak zorunda kalmadan arayabilirsiniz out.


37

Daha sonra göz ardı edeceğiniz bir değişken tanımlamalısınız. Bu, kullanıcı girdisinin geçerliliğini test etmek için kullanıldığında (örneğin, bir sayı olarak ayrıştırılabilir mi?) Gerçek ayrıştırılmış değeri önemsemeden TryParse (veya TryWhatever) modelinde en yaygın durumdur.

Soruda "dispose" kelimesini kullandınız, ancak bunun talihsiz olduğundan şüpheliyim - ancak out parametresi IDisposable uygulayan bir türdeyse, yöntem dokümantasyonu değeri almanın vermediğini açıkça belirtmedikçe kesinlikle Dispose çağırmalısınız. mülkiyet. Tek kullanımlık outparametresi olan bir yöntem gördüğümü hiç hatırlamıyorum , bu yüzden bunun şanssız bir kelime seçimi olduğunu umuyorum.


Pragmatik bir anti-
modelden

11

Orijinal işlev şu şekilde bildirilirse:

class C
{
    public Result MakeMyCall(Object arg, out List<String> messages);
}

Bunun gibi bir uzatma yöntemi tanımlayabilirsiniz:

static class CExtension
{
    public static Result MakeMyCall(this C obj, Object arg)
    {
        List<String> unused;
        return obj.MakeMyCall(arg, out unused);
    }
}

Uzantı yöntemi, out parametresini isteğe bağlı hale getiren bir aşırı yük gibi davranacaktır.


4

Visual Basic derleyicisi bunu bir kukla değişken oluşturarak yapar. Microsoft'u bunun iyi bir fikir olduğuna ikna edebilirseniz, C # bunu yapabilir.


0

messagesUygulama sınıfı varsa, IDisposableonu görmezden gelmemelisiniz. Aşağıdaki yaklaşıma benzer bir şey düşünün (bir süredir C # yazmadığım için sözdizimsel olarak doğru olmayabilir):

using (FooClass messages) {
    myResult = MakeMyCall(inputParams, messages);
}

usingBloğun dışına çıktıktan sonra messagesotomatik olarak atılacaktır.


1
İlginç. Ancak, kullanım deyimindeki değişkeni ilklendirmeniz gerekmiyor mu?
OregonGhost

1
@OregonGhost: Evet, var. Ve use deyimindeki değişkenin değerini değiştirirseniz, yine de elden çıkarılan orijinal değerdir.
Jon Skeet

@JonSkeet Hala elden çıkarılan orijinal değeri
Orkhan Alikhanov

@OrkhanAlikhanov: Derleyici temelde usingifadenin başında değişkenin bir kopyasını alır . Yani bu değişkenin blok içindeki değerini değiştirmek, hangi nesnenin atılacağını değiştirmez.
Jon Skeet

Bu arada olmalı out messages.
Orkhan Alikhanov

0

Out parametresi için bir değişken iletmelisiniz. Değişkeni geçmeden önce ilklendirmeniz gerekmez:

MyMessagesType messages;
myResult = MakeMyCall(inputParams, out messages); 

Tipik olarak, aramadan sonra 'mesajları' yok sayabilirsiniz - sınırlı sistem kaynaklarının kullanılması gibi bir nedenle 'mesajların' imha edilmesi gerekmediği sürece, bu durumda Dispose () 'u çağırmanız gerekir:

messages.Dispose();

Önemli miktarda bellek kullanabiliyorsa ve bir süre kapsamda kalacaksa, bir referans türü ise büyük olasılıkla null'a veya bir değer türü ise yeni bir varsayılan örneğe ayarlanmalıdır, böylece çöp toplayıcı hafızayı geri alabilir:

messages = null; // Allow GC to reclaim memory for reference type.

messages = new MyMessageType(); // Allow GC to reclaim memory for value type.

0

Bu durumda, ConcurrentDictionary için Delete veya Remove yöntemine sahip olmayan genel bir uzantı yöntemi yaptım.

//Remove item from list and ignore reference to removed item
public static void TryRemoveIgnore<K,T>(this ConcurrentDictionary<K,T> dictionary, K key)
{
    T CompletelyIgnored;
    dictionary.TryRemove(key, out CompletelyIgnored);
}

ConcurrentDictionary örneğinden çağrıldığında:

ClientList.TryRemoveIgnore(client.ClientId);
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.