tags:

views:

778

answers:

6

Ok, in Perl causing an object to reinitialize itself is easy since it is represented by an assignable reference or pointer. C#, however, doesn't appear to like this.

I wanted to create a subclass of System.Text.RegularExpressions.Regex whose pattern could be changed without using new objects and consuming memory for each. (private initialize references wouldn't let me run it again so I tried recreating the object reference).

Is this possible to do without creating a full wrapper around the parent object with re-implementation of every method to point to a private regex object that is reinitialized for each new use? Is there a better way?

public class m_Regex : System.Text.RegularExpressions.Regex{

    public m_Regex(string pattern): base (pattern){

    }

    public void Pattern(string pattern){
        this = new m_Regex(pattern);
    }   
}
A: 

Hi Steve

C# does not support such a syntax. In fact if you try compile your code, you'll get a compile error stating that: "this is a read-only property". Unfortunately, no luck for you today. :)

Another way is not to base your class on a Regex but have a wrapper class. For example.

public class Wrapper
{
 private Regex _regex;
 public Wrapper(string pattern)
 {
  _regex = new Regex(pattern);
 }
}
Ray Booysen
Right, What Iam wondering... is there a way to do this at all?
Steve
Ok , but now for every Member of _regex I have to create a corresponding Wrapper member correct? Hardly saving typing :P I think.
Steve
A: 

I wonder if there is a good external Regex "competitor" to the built-in .NET one that you could use for this.

Maybe = http://www.codeguru.com/Cpp/Cpp/string/regex/article.php/c2779/

tyndall
+2  A: 

I'm not sure exactly what problem you're trying to solve. If you're concerned about the amount of memory being used, perhaps due to rapid creation/deletion of Regex objects, then you could have your wrapper implement IDisposable and wrap them in a using block so that the resources are freed more rapidly. If the number of Regex objects is fairly small, then I'm not sure that I would worry too much about it. Once the object goes out of scope it can be garbage collected. If the Regex object are fixed, you may also want to think about creating static instances of each in a "regex factory" that you can use over and over.

tvanfosson
I didn't want to type `blah = new System.Text.RegularExpressions.Regex("foo");`every time I changed the pattern I was looking for. And I wanted it to be more readable when I did it. And save memory if I could.
Steve
Add "using System.Text.RegularExpresssions" to the top of your code file, then do: var blah = new Regex("foo"); I think the saving of memory should wait until you know it's a problem.
tvanfosson
+1  A: 

The reason the System.Text.RegularExpressions.Regex class behaves this way is because it is immutable. Thus, you cannot change the pattern once the Regex object has been created. In short, there is no way to do what you want to do, i.e., re-initialize the existing object with a new pattern. If you want to change the pattern, by definition, you'll have to create a new Regex object.

Matt Davis
Right I know that... I want a subclass that can be changed.
Steve
Subclassing isn't going to solve the problem because the Regex base class is still immutable.
Matt Davis
A: 

After some mucking about I found that this does what I want with some (minor) semantic differences

`public class m_Regex : System.Text.RegularExpressions.Regex{

 public m_Regex(string pattern): base (pattern){

 }

 public m_Regex Pattern(string pattern){

  return new m_Regex(pattern);
 }


}`

So now I can use pattern to 'redefine' the current regex by assigning a new object reference to the holding variable instead of replacing the instance itself. And so now (presumably) the previous regex reference is marked for the GC since nobody is using it anymore and the more palatable and self documenting

myregex = myregex.Pattern("^NewPattern$"); can be used giving the functional illusion of pattern changing regex, although I think I still would have preferred to be able to just simply invoke the member and cause it to happen completely behind the scenes.

So am I right? Will GC pickup all the used regexes following this sort of pattern? Will it do so even while the current instantiation is in scope? When does GC happen?

Steve
Garbage collection is non-deterministic but you can force the garbage collector to execute if absolutely necessary. (Are you sure you need to do that?)
Jason
Not really, but how does one do that ?
Steve
If you're not sure that you need to do that, you probably don't need to. But look at System.GC at least for self-edification.
Jason
Thanks Jason. I'm planning on messing with parsing , and the regex may be employed in recursive routines so I am leery of having little objects of short useful lifespan scattered all over the memscape. Thanks for the pointer to System.GC
Steve
A: 
//First use
myregex = new RegEx("^Pattern$");    
// later on in the code, i need to change pattern
// this call is different to the first, and i can't tell why..
myregex = myregex.Pattern("^NewPattern$");

If I were to look at code where this pattern was used, I would immediately jump to the implementation of .Pattern to understand why the 'next' use of myregex was different from the first. My expectation would be that the construction of the new regex was influenced by the state of the current regex instance (I've been trying and failing to how it would be influenced though).

.Pattern has the feel of a factory method, but it's on an instance of itself, which I find confusing and doesn't appear to add any value over the direct use of the RegEx constructor.

Regarding the GC question, the GC can be forced to run with a call to GC.Collect() but it's asking for a collection is an exceptional thing and shouldn't be called as a rule.

headsling
Perhaps its my perl background, but I like my code to 'speak' to me. This form doesn't disturb me, but I don't like new all over the place in my code. It just doesn't look right to me. Microsoft seems to be insisting on littering the memscape by making this class unable to change its pattern.
Steve
Infact in my research I found that another class behaves exactly like this ! string is also immutable and has built in methods that return a new string object. see:http://codebetter.com/blogs/patricksmacchia/archive/2008/01/13/immutable-types-understand-them-and-use-them.aspx
Steve
Your String example is perfect! The string methods to return new strings return a new object _based on the current string_. Your .Pattern simply returns a new regex with the given new pattern - nothing from the current regex is carried over.
headsling