C# 非持久“static”关键字?

发布于 2024-08-04 17:24:51 字数 442 浏览 1 评论 0原文

我有 C/C++ 背景,在 C# 中做一些事情时遇到困难。我现在的问题是我需要一个像 C++ 中一样工作的 static 关键字。这样该属性对于该类的所有实例都是全局的,这就是 C# 所做的。但我不想要的是 C#(/ASP.NET) 中的持久性。我希望静态属性仅适用于当前执行页面上的类的所有实例。

这怎么可能呢?

基本上我使用它的目的是唯一的命名,它只能在当前执行的页面上是唯一的。如果静态属性是持久的,那么在高流量期间整数翻转的可能性就会更高,这可能会导致相同的值被使用两次。

就像如果有人访问一个页面,

static int i=0;
page_load...{
  lbl.Text=i;
  i++;
}

那么他们会得到 0。如果其他人访问同一页面,他们也会得到 0。但也有静态属性,以便它在类的所有实例中都是相同的。

I come from a C/C++ background and am having trouble doing some things in C#. My problem right now is that I need a static keyword that works like in C++. So that the property is global to all instances of the class, which is what C#'s does. But what I don't want is the persistence in C#(/ASP.NET). I want the static property global to all instances of a class on the currently executing page only.

How can it be possible to do this?

Basically what I'm using this for is unique naming which must only be unique on the currently executing page. If the static property is persistent, then there is a much higher chance of integer rollover in periods of high traffic, which could lead to the same value being used twice.

Like if someone went to a page with

static int i=0;
page_load...{
  lbl.Text=i;
  i++;
}

then they would get 0. and if someone else went to the same page they would also get 0. But also having the static property so that it's the same in all instances of the class.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

单身狗的梦 2024-08-11 17:24:51

不幸的是,在这种情况下你将无法获得你想要的东西,因为你试图组合两个不兼容的概念

  • static 是 C# 中的一个修饰符,它将成员(方法、属性、字段等)从被绑定到一个实例。它的实例更准确地绑定到 AppDomain 中的类型。
  • 特定于当前执行页面的计数器必然与实例相关联,

我认为最好的选择是创建实例级属性并执行传递实例和更新计数器所需的操作。

但我对你的情况还是有点不清楚。似乎您可能需要以下任何一个...

  • 特定于执行页面的当前实例的属性
  • 特定于执行页面的所有实例的
  • 属性特定于当前会话中页面的所有使用的属性

您可以吗澄清其中哪一个是问题所在?

Unfortunately you're not going to be able to get what you want in this case because you're trying to combine two incompatible concepts

  • static is a modifier in C# which frees a member (method, property, field, etc ...) from being bound to an instance. It's instance more accurately bound to a type within an AppDomain.
  • A counter specific to the current executing page is necessarily associated with an instance

I think your best bet is to create an instance level property and do what is needed to pass down the instance and update the counter.

But I'm still a bit unclear about your scenario. It seems like you could want any of the following ...

  • A property specific to the currently instance of the executing page
  • A property specific to all instances of the executing page
  • A property specific to the all uses of the page within the current session

Could you clarify which of these is the problem?

秋意浓 2024-08-11 17:24:51

没有真正干净的方法来做到这一点,但如果您的对象始终存在于 HTTP 页面/请求的上下文中,您可以使用 当前 HttpContextItems 集合

public class YourClass
{
    private static readonly string _itemKey = "Key Goes Here";
    private readonly HttpContext _context;

    public YourClass()
    {
        _context = HttpContext.Current;
        if (_context == null) throw new InvalidOperationException("Boom!");

        // set a default value here if you like...
        if (_context.Items[_itemKey] == null)
        {
            _context.Items[_itemKey] = new YourType("Default Value");
        }
    }

    public YourType NonPersistentStatic
    {
        get { return (YourType)(_context.Items[_itemKey]); }
        set { _context.Items[_itemKey] = value; }
    }
}

There's no really clean way to do this, but if your object will always live in the context of a HTTP page/request, you could use the Items collection of the current HttpContext:

public class YourClass
{
    private static readonly string _itemKey = "Key Goes Here";
    private readonly HttpContext _context;

    public YourClass()
    {
        _context = HttpContext.Current;
        if (_context == null) throw new InvalidOperationException("Boom!");

        // set a default value here if you like...
        if (_context.Items[_itemKey] == null)
        {
            _context.Items[_itemKey] = new YourType("Default Value");
        }
    }

    public YourType NonPersistentStatic
    {
        get { return (YourType)(_context.Items[_itemKey]); }
        set { _context.Items[_itemKey] = value; }
    }
}
手心的温暖 2024-08-11 17:24:51

我不太确定我 100% 理解你的问题...

我相信你真正想要的是在会话中存储一个对象。

我要做的是这样的

public class PageBase : Page
{

    public MyObject Foo 
    {
        get { return (MyObject)Session["myobject"]; }
        set { Session["myobject"] = value; }
    }
}

并将您的页面更改为从 PageBase 继承

编辑: 在查找 ASP.NET 内 [ThreadStatic] 的含义后,我发现了这个博客Scott Hanselmen 发帖说,不不不! 两种技术的故事:[ThreadStatic] 属性和 System.Web.HttpContext.Current.Items< /a>.他还指出 HttpContext 的存在,它有一个内置字典,您可以在其中存储对象。我完全忘记了这一点,主要是因为到目前为止我从未发现过任何有用的东西。

I'm not really sure I understand your question 100% however...

I believe what your really looking for is to store an object in the Session.

What I would do is something like this

public class PageBase : Page
{

    public MyObject Foo 
    {
        get { return (MyObject)Session["myobject"]; }
        set { Session["myobject"] = value; }
    }
}

And change your pages to inherit from PageBase

Edit: After looking up the implications on [ThreadStatic] inside ASP.NET I came across this blog post by Scott Hanselmen saying, no no no! A tale of two techniques: The [ThreadStatic] Attribute and System.Web.HttpContext.Current.Items. He also pointed out the existence of the HttpContext having a builtin dictionary that you can store objects in. I forgot entirely about this mostly because so far I've never once found anything useful for it.

ぽ尐不点ル 2024-08-11 17:24:51

您从哪里引用“静态”?如果它只是子控件,我会向页面类添加一个常规实例属性,然后通过子控件上的页面属性引用该变量。

public class DefaultPage : Page {
    public string MyProperty { get; set; }
} 

public class DefaultControl : UserControl {
    //...
    ((DefaultPage)this.Page).MyProperty
    //...
}

老实说,如果我看到这段代码,我会认为设计有点落后。页面应该向用户控件提供其所需的所有数据。

Where are you referencing the "static" from? If it is just child controls, I would add a regular instance property to your page class, then reference that variable through the page property on the child controls.

public class DefaultPage : Page {
    public string MyProperty { get; set; }
} 

public class DefaultControl : UserControl {
    //...
    ((DefaultPage)this.Page).MyProperty
    //...
}

Honestly though, if I saw this code, I would think the design is a little backwards. Page should be supplying the user control with all of the data it needs.

羁客 2024-08-11 17:24:51

您要求的是 ThreadStatic 变量,但这不是一个好的解决方案。它会起作用,但这不是一个可靠的处理方法。例如,ThreadStatic 变量仅针对第一个线程进行初始化,因此您需要自己处理每个线程的初始化。

首先,您应该研究内置功能,为每个元素提供唯一的 id。例如,如果您有一个中继器,以便重复相同的控件,则每次迭代都会获得一个唯一的 id,该 id 会添加到控件 id 之前。您可以使用 ClientID 属性来获取此唯一 ID。

如果您需要自己处理命名,则应使用 Page 类中的成员变量来跟踪命名。您可以轻松地在类的构造函数中初始化该变量,并且由于该变量在此之前不存在,因此您可以确定在初始化之前不会意外使用它。

What you are asking for is a ThreadStatic variable, however that is not a good solution. It would work, but it's not a robust way to handle it. A ThreadStatic variable is for example only initialized for the first thread, so you need to handle the initialization for each thread yourself.

First of all you should look into the built in capabilities for providing a unique id for each element. If you for example have a repeater so that the same control is repeated, each iteration gets a unique id which is prepended to the control id. You can use the ClientID property to get this unique id.

If you need to handle the naming yourself, you should use a member variable in the Page class to keep track of the naming. You can easily initialize the variable in the constructor of the class, and as the variable doesn't exist before that, you are sure that you can't accidentally use it before it's initialized.

别挽留 2024-08-11 17:24:51

不知道为什么你需要它。您可以在 HTTPContext.Current.Session 中存储会话特有的内容。您可以在 HTTPContext.Current.ViewState 中存储请求特有的内容。

要执行您想做的操作,您需要声明一个线程安全的对象的应用程序范围变量。下面的示例将为您提供跨所有页面的唯一编号。

1) 创建一个线程安全的计数器类,因为默认情况下 Application 作用域变量不是线程安全的

public class ThreadSafeCounter
{
  private object _padlock = new object;
  private int _counterValue = 0;

  public int GetNextValue()
  {
     int temp;
     lock(_padlock)
     {
       _counter++;
       temp = _counter;
     }
     return temp;
  }

}

2) 在 Global.asax Application_Start 事件中创建应用程序变量

HttpContext.Current.Application["MyCounter"] = new ThreadSafeCounter();

3) 在页面的代码后面访问它

var counter = HttpContext.Current.Application["MyCounter"] as ThreadSafeCounter;
if (counter != null)
{
  var uniqueValue = counter.GetNextValue();
  // DO SOME WORK HERE
}
else
{
  //throw some exception here
}

潜在的陷阱:< /强>
如果您跨服务器场部署它或者您有超过 1 个工作进程,请确保您的会话模式是基于状态服务器或 SQL Server,因为如果它是 InProc,则处理请求的每个服务器/进程都将拥有自己的会话模式柜台。

Not sure why you would need that. You can store stuff unique to a session in the HTTPContext.Current.Session. You can store stuff that is unique to a request in HTTPContext.Current.ViewState.

To do what you want to do, you would need to declare an application scopped variable of an object that that is threadsafe.The example below example would give you a unique number across all pages.

1) Create a thread-safe counter class since the Application scopped variables are not thread safe by defaut

public class ThreadSafeCounter
{
  private object _padlock = new object;
  private int _counterValue = 0;

  public int GetNextValue()
  {
     int temp;
     lock(_padlock)
     {
       _counter++;
       temp = _counter;
     }
     return temp;
  }

}

2) Create the application variable in the Global.asax Application_Start event

HttpContext.Current.Application["MyCounter"] = new ThreadSafeCounter();

3) Access this in your page's code behind

var counter = HttpContext.Current.Application["MyCounter"] as ThreadSafeCounter;
if (counter != null)
{
  var uniqueValue = counter.GetNextValue();
  // DO SOME WORK HERE
}
else
{
  //throw some exception here
}

A potential gotcha:
If you deploy this across a server farm or you have more than 1 worker process, make sure that your session mode is either a state server or SQL Server based because if it is InProc the each server/process that handles the request will have its own counter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文