Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

[C#] Bestaat deze language feature?

Pagina: 1
Acties:

  • NickThissen
  • Registratie: november 2007
  • Laatst online: 23:28
Het viel me op dat ik in een MVC project veel code schrijf die volgens mij wat korter kan met een language feature die (voor zover ik weet) niet bestaat. Ik dacht laat ik eens vragen of ik misschien iets over het hoofd zie :) Het duurde bijvoorbeeld ook best lang voordat ik afwist van de nieuwe null-conditional operator. Misschien bestaat er al iets, of misschien is het wel helemaal niet nuttig of uberhaupt mogelijk.

Wat ik voorstel als language feature is eigenlijk een conditional return statement. Als het statement iets (anders dan null) terug geeft dan gedraagt het zich als een normale return (en geeft die waarde terug), maar als er null terug komt dan gaat de code verder (in plaats van terug geven van null).

Een voorbeeld, stel dat ik in een MVC app vaak moet kijken of een gebruiker wel een bepaalde actie mag uitvoeren. Bijvoorbeeld het wijzigen van een "team" (wat dat dan ook is) wat alleen mag als de gebruiker admin rechten heeft voor dat team:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[Authorize]
public ActionResult Edit(int id)
{
    // Zoek team
    Team team = db.Teams.Find(id);
    if (team == null)
        return HttpNotFound();
        
    // Vind gebruiker
    User user = GetUser(); // zie beneden
    
    // Check rechten voor dit team
    if (!IsTeamAdmin(user, team))
        return new HttpUnauthorizedResult();
        
    // Doe de edit
    ...
    
    return View(team);
}

private bool IsTeamAdmin(User user, Team team)
{
    return team.IsAdmin(user);
}

private User GetUser()
{
    return UserManager.FindById(User.Identity.GetUserId());
}


Het gaat om regel 13/14. Dit stukje code komt natuurlijk overal in de controller voor, bij het opvragen van de Edit, dan opnieuw bij het posten van de Edit, hetzelfde voor Delete, toevoegen van andere users, etc.

Ik voorzie eigenlijk een "conditional return" statement, bijvoorbeeld "return?" wat dan als volgt werkt:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[Authorize]
public ActionResult Edit(int id)
{
    // Zoek team
    Team team = db.Teams.Find(id);
    if (team == null)
        return HttpNotFound();
        
    // Vind gebruiker
    User user = GetUser(); // zie beneden
    
    // Check rechten voor dit team
    return? CheckIsTeamAdmin(user, team);
        
    // Doe de edit
    ...
    
    return View(team);
}

private ActionResult CheckIsTeamAdmin(User user, Team team)
{
    if (!team.IsAdmin(user))
            return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
    return null;
}

private User GetUser()
{
    return UserManager.FindById(User.Identity.GetUserId());
}


De return statement is nu dus eigenlijk verplaatst naar de CheckIsTeamAdmin functie, met als resultaat dat ik niet elke keer opnieuw de "return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);" hoef te typen.

Het idee is dus dat CheckIsTeamAdmin null terug geeft als de user inderdaad admin is, en dat de code daarna verder gaat na de "return?" regel, in plaats van stopt.


In dit voorbeeld scheelt het natuurlijk niks maar hoe vaker je deze check moet doen hoe meer het scheelt.

Dit bestaat niet, toch? Zou dit een leuke feature zijn, of mis ik iets waardoor dit totaal niet kan werken?

Het enige wat ik kan bedenken dat misschien problemen geeft is het "speciale" gedrag van null terug geven als je de code wil laten verder lopen. Eventueel zou je ook gewoon geen return statement kunnen doen als de conditie niet goed is, dus bijvoorbeeld:
C#:
1
2
3
4
5
6
private conditional ActionResult CheckIsTeamAdmin(User user, Team team)
{
    if (team.IsAdmin(user))
            return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
    // geen return
}

Dit mag natuurlijk nu niet, dus om het de compiler wat makkelijker te maken verzin ik maar een 'conditional' woord in de declaratie van de functie (anders zou ELKE functie in principe legaal zijn zonder return en dat gaat natuurlijk problemen geven).


Zomaar iets waar ik aan zat te denken, heeft het zin om dit als feature aan te dragen ofzo? :+

Mijn iRacing profiel


  • NickThissen
  • Registratie: november 2007
  • Laatst online: 23:28
Goed, niet het beste voorbeeld, maar daar gaat het niet om.

Een ander voorbeeld dan;

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public int GetSomeValue()
{
    if (!Check1())
        return 0;
    if (!Check2())
        return 18;
    if (!Check3())
        return 23;
    if (!Check4())
        return new DefaultValuesGetter().DefaultReturnValue;
        
    return 1 + 1;
}

// Of:
public int GetSomeValueConditional()
{
    return? Check1();
    return? Check2();
    return? Check3();
    return? Check4();
    return 1 + 1;
}


Het idee is om de logica van de "check" (in eerste voorbeeld "mag de gebruiker dit doen?") samen te koppelen met de waarde die terug gegeven moet worden als die check niet goed is.

In "GetSomeValue" geven de "Check" functies booleans terug, die ik eerst moet checken en daarna nog moet vertellen wat GetSomeValue dan moet terug geven (als er "false" terug komt).

In "GetSomeValueConditional" geven de "Check" functies meteen de waarde terug die ik terug wil sturen (0, of 18, of 23, of...).

Gewoon ietsje korter, ik denk dat het best handig kan zijn in veel gevallen.

Mijn iRacing profiel


  • NickThissen
  • Registratie: november 2007
  • Laatst online: 23:28
RobIII schreef op donderdag 17 december 2015 @ 15:04:
[...]

Ik vind 't maar raar... je tweede voorbeeld returned helemaal niet de 0, 18, 23, ... values? Of komen die dan spontaan uit CheckX()?
Precies:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public int? Check1()
{
    if (!SomeCheck())
        return 0;
    return null;
}
public int? Check2()
{
    if (!SomeOtherCheck())
        return 18;
    return null;
}
public int? Check3()
{
    if (!SomeThirdCheck())
        return 23;
    return null;
}

Enzovoorts.

Met de ternary operator kom je nog wel een eind in dit voorbeeld, maar dat is eigenlijk alleen omdat de acties die volgen na alle checks in dit geval maar een regeltje is (return 1 + 1). Stel dat je daar nog een sloot werk moet doen dan past dat niet in een ternary (of je moet dat weer in een aparte method stoppen). De leesbaarheid wordt er niet veel beter van.

Ik vind mijn "return?" nog best leesbaar, als je het leest als "return iets, of anders ga door".

Mijn iRacing profiel

Pagina: 1


Apple iPhone 12 Microsoft Xbox Series X LG CX Google Pixel 5 Black Friday 2020 Samsung Galaxy S20 4G Sony PlayStation 5 Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2020 Hosting door True