2015-06-19 8 views
6

?? işleci, listedeki en iyi eşleşmeyi temel alarak bir nesneyi denemek ve atamak için kullanıyorum.Boştaki birleştirici işleçte hangi sol el öğesinin başarıyla atanmış olduğunu yakalama

Çeşitli eşleştirme kuralları vardır ama örneğin bu basitleştirilmiş var: Hata ayıklama amacıyla

objectImTryingToSet = 
MyListOfPotentialMatches.FirstOrDefault(*/lamda checking numerous things*/) ??     //rule1 
MyListOfPotentialMatches.FirstOrDefault(*/lamda checking different numerous things*/) ??  //rule2 
MyListOfPotentialMatches.FirstOrDefault(*/lamda checking again different numerous things*/); //rule3 

, ben bir hata var olarak başarıyla objectImTryingToSet atanan biriydi kural dize günlüğü saklamak istiyorum bir senaryoda, nesne, olması gerekmediğinde ve gerçek bir baş ağrısının, yanlış atamanın nerede yattığını bulmak için el ile tüm bu kuralları gözden geçirmeye çalıştığı zaman atanmaktadır.

string ruleThatMatched = null; 

objectImTryingToSet = 
MyListOfPotentialMatches.FirstOrDefault(*/lamda checking numerous things*/) ?? if (objectImTryingToSet != null) { ruleThatMatched = "rule1" }     //rule1 
MyListOfPotentialMatches.FirstOrDefault(*/lamda checking different numerous things*/) ?? if (objectImTryingToSet != null) { ruleThatMatched = "rule2" }  //rule2 
MyListOfPotentialMatches.FirstOrDefault(*/lamda checking again different numerous things*/); if (objectImTryingToSet != null) { ruleThatMatched = "rule3"}  //rule3 

//tried all the rules and still no match 
if (objectImTryingToSet == null) 
{ 
    ruleThatMatched = "no rule managed to find a match"; 
} 

?? operatörü kullanılarak bu bile mümkün mü:

Yani temelde sözde, ister misin?

+9

Neden kullandığınız bir 'eğer ... else' yok?Üçlü veya null-birleştirme işlecini kullanırken –

+2

ve bunu daha karmaşık hale getirmeye başladığınızda, eğer/else veya switch'e geçiş yapmaktan daha iyidir. – Jonesopolis

+4

"Doktor, ben * bu * ne zaman acıyor!" "Şunu yapmayı kes." ... Üzgünüm, dayanamadım. :) –

cevap

2

Böyle yapabilirsiniz:

var res = 
    MyListOfPotentialMatches.Select(v => new {r=1, v}).FirstOrDefault(/*lamda checking numerous things*/) ?? 
    MyListOfPotentialMatches.Select(v => new {r=2, v}).FirstOrDefault(/*lamda checking different numerous things*/) ?? 
    MyListOfPotentialMatches.Select(v => new {r=3, v}).FirstOrDefault(/*lamda checking again different numerous things*/); 
if (res != null) { 
    var ruleNumber = res.r; 
    objectImTryingToSet = res.v; 
} 

anahtar kodlanmış kural numarası ile sonuç kadar Select hangi çifttir. Çok Eğer ?? operatör olmadan yapabileceğini

Not:

var firstChoice = MyListOfPotentialMatches.Select(v => new {r=1, v}).Where(/*lamda checking numerous things*/); 
var secondChoice = MyListOfPotentialMatches.Select(v => new {r=2, v}).Where(/*lamda checking different numerous things*/); 
var thirdChoice = MyListOfPotentialMatches.Select(v => new {r=3, v}).Where(/*lamda checking again different numerous things*/); 
var res = firstChoice.Concat(secondChoice).Concat(thirdChoice).FirstOrDefault(); 
if (res != null) { 
    var ruleNumber = res.r; 
    objectImTryingToSet = res.v; 
} 
+0

, bu nedenle, salt okunur bir özellik eklemek için Anonymous Types kullanıyor mu? – JsonStatham

+0

@SelectDistinct Evet, işte böyle. – dasblinkenlight

+0

Başlarken "Hata " MySolution.Core.AddressService.JsonAddressModel "ifadesinin" AnonymousType # 1 "türünü dolaylı olarak dönüştürememesi, bilgi için şu şekilde gözüküyor: Addresses.Select (v => new {r = 1, v}) FirstOrDefault (v => vvpaon.Trim() == exception.AddressLineOne && vvdthorofare.Trim() == exception.AddressLineTwo); – JsonStatham

0

Böyle bir şey mi arıyorsunuz?

static void Main(string[] args) 
{ 
    List<int?> intList = new List<int?>() { 3, 4}; 


    Func<int?, bool> rule = null; 

    var value = intList.FirstOrDefault(rule = (i => i == 1)) 
      ?? intList.FirstOrDefault(rule = (i => i == 2)) 
      ?? intList.FirstOrDefault(rule = (i => i == 3)) 
      ?? intList.FirstOrDefault(rule = (i => i == 4)); 
} 

Not olarak, bu yalnızca dil ile neler yapabileceğinizi araştırmak içindir. Bunu üretim kodunda gerçekten yapmanı tavsiye etmem. Okuması gerekenden daha zor. Bilmiyorum, çünkü burada


Eğer bu sizin sözde kodunun yakınına görünüyor ki

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<int?> intList = new List<int?>() { 3, 4}; 

     List<RuleModel> Rules = new List<RuleModel>(); 

     Rules.Add(new RuleModel{Name = "Rule1", Rule = (i => i == 1)}); 
     Rules.Add(new RuleModel{Name = "Rule2", Rule = (i => i == 2)}); 
     Rules.Add(new RuleModel{Name = "Rule3", Rule = (i => i == 3)}); 
     Rules.Add(new RuleModel{Name = "Rule4", Rule = (i => i == 4)}); 

     int? valueToSet = null; 

     var ruleUsed = Rules.FirstOrDefault(r => (valueToSet = intList.FirstOrDefault(r.Rule)) != null); 
    } 

} 

public class RuleModel 
{ 
    public Func<int?, bool> Rule { get; set; } 
    public string Name { get; set; } 
} 
2

(Edited alabilir başka bir yaklaşım, ancak bazı boşlukları doldurmak gerekecek nesnenizin tipi)

string ruleThatMatched = null; 
Func<string, TypeOfObjectImTryingToSet, TypeOfObjectImTryingToSet> getAndTrackRule = 
    (ruleText, obj) => 
     { 
      ruleThatMatched = ruleText; 
      return obj; 
     }; 


var objectImTryingToSet = 
    getAndTrackRule("rule1", MyListOfPotentialMatches.FirstOrDefault(*/lamda checking numerous things*/)) ?? 
    getAndTrackRule("rule2", MyListOfPotentialMatches.FirstOrDefault(*/lamda checking different numerous things*/)) ?? 
    getAndTrackRule("rule3", MyListOfPotentialMatches.FirstOrDefault(*/lamda checking again different numerous things*/)); 

if (objectImTryingToSet == null) 
{ 
    Console.WriteLine("no rule managed to find a match"); 
} 
else 
{ 
    Console.WriteLine(string.Format("Final value {0} found by applying rule {1}", objectImTryingToSet, ruleThatMatched)); 
} 
0

Eğer dışarı argümanla 3 kontrol fonksiyonlarını oluşturmalıdır.

function bool check1(YourObject obj, out string ruleMatched) 
{ 
    ruleMatched = "rule1"; 
    return /* checking numerous things */; 
} 

// same for each checking 

string ruleMatched; 
objectImTryingToSet = 
MyListOfPotentialMatches.FirstOrDefault(x => check1(x, out ruleMatched)) ?? //rule1 
MyListOfPotentialMatches.FirstOrDefault(x => check2(x, out ruleMatched)) ?? //rule2 
MyListOfPotentialMatches.FirstOrDefault(x => check3(x, out ruleMatched)); //rule3 
+0

Yani her bir kuralı bir yönteme yerleştirmenizi öneriyor musunuz? – JsonStatham

+1

@SelectDistinct evet, daha fazla okunabilirlik ve yeniden kullanılabilirlik katacak. – aleha

2

Kendi mantığınızı saran özel bir uzantı yöntemi hazırladım. Güzel değil, ancak standart FirstOrDefault yerine bunu çağırabilirsiniz. out parametresi olarak ek bir string ve istediğiniz hata ayıklama mesajı olarak başka bir string alır.

public static T GetFirstWithMessage<T>(this IEnumerable<T> collection, 
             Func<T, bool> matchFunc, 
             out string outputString, 
             string message) 
{ 
    var match = collection.FirstOrDefault(matchFunc); 
    outputString = match == null ? null : message; 
    return match; 
} 

Daha sonra bunları bunlarla bir araya getirebilirsiniz.

string matchedRule; 

var matchedFruit = fruits.GetFirstWithMessage(f => f.Count < 1, out matchedRule, "Out of stock") 
    ?? fruits.GetFirstWithMessage(f => f.Name.Length > 10, out matchedRule, "Long name") 
    ?? fruits.GetFirstWithMessage(f => !f.IsFresh, out matchedRule, "Rotten Fruit") 
    ?? fruits.GetFirstWithMessage(f => f.Count > 24, out matchedRule, "Big group"); 

A demo

+0

@SelectDistinct bu güzel !! –

İlgili konular