Performance of String literals vs constants for Session[…] dictionary keys

会有一股神秘感。 提交于 2019-12-01 15:10:38

The reason to use constants has to do with maintainability, not performance. Performance is about the same either way.

With a string literal, you can never tell whether it's the same as another string literal intentionally or by coincidence, so when it's time to change one, you don't know which other ones to change. But if you have the values in constants, you just make the change in one place.

Bad:

ViewData["username"] = Session["username"];

Good:

const UserNameSessionKey = "username";
const UserNameViewDataKey = "username";

ViewData[UserNameViewDataKey] = Session[UserNameSessionkey];

Now imagine changing the value of the session key to "userName" without wanting to change it for any viewdata key...

Use the constant because the compiler will give you an error if you mistype it, whereas mistyped strings will just give you wonky bugs.

The performance difference will likely be so small it would be very difficult to measure.

Lets go further with maintainability. I'll quote my other answer about using Session:

Lets say we want to store shopping cart is Session of our ASP.NET MVC application. It will be stored in Session["ShoppingCart"], but we want easy, strongly typed access and high testability:

First we define interface:

public interface ISessionWrapper
{
    List<CartItem> ShoppingCart { get; set; }
}

Then we make HttpContext implementation:

public class HttpContextSessionWrapper : ISessionWrapper
{
    private T GetFromSession<T>(string key)
    {
        return (T) HttpContext.Current.Session[key];
    }

    private void SetInSession(string key, object value)
    {
        HttpContext.Current.Session[key] = value;
    }

    public List<CartItem> ShoppingCart
    {
        get { return GetFromSession<List<CartItem>>("ShoppingCart"); }
        set { SetInSession("ShoppingCart", value); }
    }
}

GetFromSession and SetInSession are helper method that make taking and setting data in Session easier. They can be easily reused to access other fields in Session.

Then we define our base controller (applicable to ASP.NET MVC):

public class BaseController : Controller
{
    public ISessionWrapper SessionWrapper { get; set; }

    public BaseController()
    {
        SessionWrapper = new HttpContextSessionWrapper();
    }
}

If you want to use Session outside controller, you just create or inject new HttpContextSessionWrapper().

You can replace SessionWrapper with ISessionWrapper mock in Controller tests, so it is not dependent on HttpContext anymore. Session is also more easy to use, because instead of calling (List<CartItem>)Session["ShoppingCart"], you call SessionWrapper.ShoppingCart. It looks nicer, isn't it?

If you don't use model class for view and I think using model class is better, you can do the same with ViewData:

public interface IViewDataWrapper
{
    List<CartItem> ShoppingCart { get; set; }
}

public class ViewDataWrapper : IViewDataWrapper
{
}

public class BaseController : Controller
{
    public IViewDataWrapper ViewDataWrapper { get; set; }

    public BaseController()
    {
        IViewDataWrapper = new ViewDataWrapper();
    }
}

And then simply in controller:

ViewDataWrapper.ShoppingCart = SessionWrapper.ShoppingCart 

or if you decide not to use ViewData and specific model:

Model.ShoppingCart = SessionWrapper.ShoppingCart

And simply in view (if you define base class for view and introduce this interface):

<%= ViewDataWrapper.ShoppingCart %>

or

<%= Model.ShoppingCart %>

No mistyped strings, strongly typed, nice looking.

Just a quick note but a lot of the better examples have a class of SessionKeys containing string constants. This also aids Unit Testing as you can call the constants in your Unit Tests where necessary.

E.g. (just one key but obviously you can add more

public class SessionKeys
{
    public const string UserDto = "UserDto";
}

used as such (I use SessionStateWrapper)

UserDto userDto = _sessionStateWrapper.GetItem(SessionKeys.UserDto) as UserDto;

According to this benchmark on the length of dictionary keys, shorter keys are faster. Quoted here:

Dictionary string key length benchmark in C#

Are shorter lookup keys significantly faster? As keys get shorter, lookup time gets faster:

  • Key A - 20 characters: 4436 ms [slowest]
  • Key B - 10 characters: 2010 ms
  • Key C - 5 characters: 1749 ms
  • Key D - 2 characters: 1575 ms [fastest]

where:

  • Key A = "01234567890123456789";
  • Key B = "0123456789";
  • Key C = "01234";
  • Key D = "01";
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!