Cosidering I can't change class ReadTheFile, is there a way how to "chain" instance methods so I don't have to reference myObject multiple times? I am looking for something like
myObject.Read().Open(param1);
I can write myObject.Open(param1).Read(); which compiles however Read() is not executed.
//myObject.Open(param1).Read(); does execute but it's executed as StreamReader method not ReadTheFile method. Overlooked VS help...
class TestT211
{
static void Main(string[] args)
{
var myObject = new ReadTheFile();
myObject.Read(myObject.Open(#"C:\file.txt"));
}
}
public class ReadTheFile
{
private int _lineCounter = 0;
private string _lineOfText;
public StreamReader Open(string path)
{
return new StreamReader(path);
}
public void Read(StreamReader sr)
{
while ((_lineOfText = sr.ReadLine()) != null) {
Console.WriteLine(_lineOfText);
}
}
}
If you want to have a syntax like a Fluent API you need to change some point of your class. First you need to have Open return the current instance and then use that instance to call Read. But this assumes that you keep the StreamReader as an internal variable of the class
public class ReadTheFile : IDisposable
{
private int _lineCounter = 0;
private string _lineOfText;
private StreamReader _sr = null;
public ReadTheFile Open(string path)
{
_sr = new StreamReader(path);
return this;
}
public void Read()
{
if(_sr == null) return;
while ((_lineOfText = _sr.ReadLine()) != null) {
Console.WriteLine(_lineOfText);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if(_sr != null)
{
_sr.Close();
_sr = null;
}
}
}
}
and now you can write
using(ReadTheFile myObject = new ReadTheFile())
myObject.Open(#"C:\file.txt").Read();
Notice that having a StreamReader between your internal variables requires you to implement the IDisposable interface to properly close and dispose the Stream
If you want to add more functionality to class without access to it, you can use extensions. For example to use ReadTheFile to read StreamReader.
public static class StreamReaderExtension
{
public static StreamReader ReadEx(this StreamReader sr)
{
var readTheFile = new ReadTheFile();
readTheFile.Read(sr);
return sr;
}
}
and than call it with
myObject.Open(#"C:\file.txt").ReadEx();
You can add more methods, but cannot override the instance ones so you have to create a new name or new signature.
Using simple builder (it's overkill) but you could achive what you want:
class TestT211
{
static void Main(string[] args)
{
FileReaderBuilder.New.Open(#"C:\file.txt").Read();
}
}
public class ReadTheFile
{
private int _lineCounter = 0;
private string _lineOfText;
public StreamReader Open(string path)
{
return new StreamReader(path);
}
public void Read(StreamReader sr)
{
while ((_lineOfText = sr.ReadLine()) != null)
{
Console.WriteLine(_lineOfText);
}
}
}
public class FileReaderBuilder
{
private readonly ReadTheFile _file;
private StreamReader _streamReader;
private FileReaderBuilder()
{
_file = new ReadTheFile();
}
public FileReaderBuilder Open(string path)
{
_streamReader = _file.Open(path);
return this;
}
public FileReaderBuilder Read()
{
if (_streamReader == null)
{
throw new ArgumentNullException(nameof(_streamReader));
}
_file.Read(_streamReader);
return this;
}
public static FileReaderBuilder New => new FileReaderBuilder();
}
Related
I am writing a small program in C# and at the start i noticed that Visual studio is complaining about having to use only static variables and static function calls in static functions (including the main). I have coded before, although i have to mention that i have coded before, and i cant remember being forced to use static everywhere. Here is the code:
class Program
{
string word = "asd";
static List<string> words = new List<string>();
static void Main(string[] args)
{
OpenFile();
Debug.WriteLine(words.Count);
anagram();
}
public static void OpenFile()
{
using (var fileStream = File.OpenRead("wordlist.txt"))
using (var streamReader = new StreamReader(fileStream))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
words.Add(line);
}
}
}
public void anagram()
{
Console.WriteLine(word);
}
}
I am getting the error " Error CS0120 An object reference is required for the non-static field, method, or property 'Program.anagram()' " and i just dont understand why? Also i wanted to make the words variable non-static as well but since the method is static that i am using it in it "has to be". Is there any way to avoid this?
I think i have a good understanding of what static is but i just don't want to use it here.
Any help is appreciated an thank you in advance.
You can define your logic into another class and create an instance of it and use its members.
public class MyClass
{
string word = "asd";
public List<string> Words = new List<string>();
public void OpenFile()
{
using (var fileStream = File.OpenRead("wordlist.txt"))
using (var streamReader = new StreamReader(fileStream))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
Words.Add(line);
}
}
}
public void anagram()
{
Console.WriteLine(word);
}
}
Then your main method would be like this:
static void Main(string[] args)
{
var m = new MyClass();
m.OpenFile();
Debug.WriteLine(m.Words.Count);
m.anagram();
}
You should read more about access modifiers and how static members and instance members are different.
You could write your class like this:
class Program
{
public string word = "asd";
public List<string> words = new List<string>();
static void Main(string[] args)
{
var program = new Program();
program.OpenFile();
Debug.WriteLine(program.words.Count);
program.anagram();
}
public void OpenFile()
{
using (var fileStream = File.OpenRead("wordlist.txt"))
using (var streamReader = new StreamReader(fileStream))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
this.words.Add(line);
}
}
}
public void anagram()
{
Console.WriteLine(this.word);
}
}
Static methods are generic to the class - if you want to use non-static, you need to instantiate an instance of it.
I want to use common trace id. I'm using following code.
public void method1(){
using (new Tracer(Guid.NewGuid().ToString()))
{
//my code
}
}
public void method2(){
using (new Tracer(Guid.NewGuid().ToString()))
{
//my code
}
}
Here guid is my trace id. But different trace id generating for every method call. I want keep it as unique. How to achieve this?. (note : I call method1,method2 from some different client)
If you need to get info about class name and/or your .NET <= 4.0, use StackFrame. You'll get some overhead with StackFrame. If you don't need to get the name of class and you use .NET >= 4.5, here is solution. It uses Caller Information. :
namespace Tracer
{
using System;
using System.Runtime.CompilerServices;
sealed class CallerInfoTracer : IDisposable
{
private readonly string _message;
private readonly string _memberName;
private readonly string _sourceFilePath;
private readonly int _lineNumber;
private bool _disposed;
public CallerInfoTracer(string message, [CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int lineNumber = 0)
{
_message = message;
_memberName = memberName;
_sourceFilePath = sourceFilePath;
_lineNumber = lineNumber;
}
public void Dispose()
{
if (_disposed) return;
Console.WriteLine("Message: {0}", _message);
Console.WriteLine("MemberName: {0}", _memberName);
Console.WriteLine("SourceFilePath: {0}", _sourceFilePath);
Console.WriteLine("LineNumber: {0}", _lineNumber);
_disposed = true;
}
}
public class Program
{
public static void Main(string[] args)
{
Method1();
Method2();
}
public static void Method1()
{
using (var tracer = new CallerInfoTracer("Desc1")) { }
}
public static void Method2()
{
using (var tracer = new CallerInfoTracer("Desc2")) { }
}
}
}
I have a question about disposing objects.
Consider this IDisposable class
public class MyClass : DisposableParentClass
{
private MyProp _prop;
public MyClass(MyProp prop)
{
_prop = prop;
}
public MyClass()
{
_prop = new MyProp();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_prop.Dispose();
}
base.Dispose(disposing);
}
}
On the first constructor, MyProp is injected. So MyClass is not the owner of the object. But on the second constructor, MyProp is created locally.
Should I always dispose MyProp, or should I check first if it is injected or not.
public class MyClass : DisposableParentClass
{
private MyProp _prop;
private bool _myPropInjected = false;
public MyClass(MyProp prop)
{
_prop = prop;
_myPropInjected = true;
}
public MyClass()
{
_prop = new MyProp();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (!_myPropInjected) { _prop.Dispose(); }
}
base.Dispose(disposing);
}
}
If your class should handle these two situations:
It is not the owner of the provided object, it should not dispose of it
It is the owner of the created object, it should dispose of it
Then yes, you need to have a mechanism that tells these two situations apart.
A common method (common to me anyway) is to use naming convention like this:
private MyProp _prop;
private bool _ownsProp = false;
ie. reverse the meaning of your flags, but this is details, your solution is just fine, and yes, you need to have a solution like this.
If you have a ton of these fields, where each must have its own bool field to handle this, it might be worth creating a helper class, such as this LINQPad program demonstrates:
void Main()
{
Injectable i1 = new Injectable();
Injectable i2 = new Injectable(new Injected("A"));
Injectable i3 = new Injectable(new Injected("A"), new Injected("B"));
Debug.WriteLine("dispose a and b");
i1.Dispose();
Debug.WriteLine("dispose b");
i2.Dispose();
Debug.WriteLine("no dispose");
i3.Dispose();
}
public class Injected : IDisposable
{
public Injected(string name) { Name = name; }
public string Name { get; set; }
public void Dispose() { Debug.WriteLine(Name + " disposed"); }
}
public class Injectable : IDisposable
{
private Ownable<Injected> _A;
private Ownable<Injected> _B;
public Injectable(Injected a, Injected b)
{
_A = Ownable.NotOwned(a);
_B = Ownable.NotOwned(b);
}
public Injectable(Injected a)
{
_A = Ownable.NotOwned(a);
_B = Ownable.Owned(new Injected("B"));
}
public Injectable()
{
_A = Ownable.Owned(new Injected("A"));
_B = Ownable.Owned(new Injected("B"));
}
public void Dispose()
{
_A.Dispose();
_B.Dispose();
}
}
public class Ownable<T> : IDisposable
where T : class
{
private readonly T _Instance;
private readonly Action _CleanupAction;
public Ownable(T instance, bool isOwned)
{
_Instance = instance;
if (isOwned)
{
IDisposable disposable = instance as IDisposable;
if (disposable == null)
throw new NotSupportedException("Unable to clean up owned object, does not implement IDisposable");
_CleanupAction = () => disposable.Dispose();
}
}
public Ownable(T instance, Action cleanupAction)
{
_Instance = instance;
_CleanupAction = cleanupAction;
}
public T Instance { get { return _Instance; } }
public void Dispose()
{
if (_CleanupAction != null)
_CleanupAction();
}
}
public static class Ownable
{
public static Ownable<T> Owned<T>(T instance)
where T : class
{
return new Ownable<T>(instance, true);
}
public static Ownable<T> Owned<T>(T instance, Action cleanupAction)
where T : class
{
return new Ownable<T>(instance, cleanupAction);
}
public static Ownable<T> NotOwned<T>(T instance)
where T : class
{
return new Ownable<T>(instance, false);
}
}
A different note can be made here either.
It depends on what is your MyClass is doing actually.
For example, if we are talking about a class that reads video stream from device, after applies some filters to it and writes data to a user specified file, where file writing is made by stream passed from the outside, say like this:
public class VideoProcessor : IDisposable {
private FileStream _videoFile = null;
private VideoProcessor() {}
//user specified FileStream
public VideoProcessor(FileStream fs) {_videoFile = fs;}
public void Dispose() {
_videoFile.Dispose(); //Dispose user passed FileStream
}
}
disposing passed stream object during dispose call, makes actually sence.
In other cases, yes, it's better to not destroy object, if you are not an owner of it. Leave it to the caller to decide when it is appropriate time to do that.
I am supposed to create a context object for the current instance of the user, and the code is
public class WorkoutContext {
protected static WorkoutContext mWorkoutContext ;
protected WorkOut mWorkOut;
protected WorkoutContext(WorkOut workout)
{
mWorkOut= workout;
}
public static WorkoutContext CreateContext(WorkOut workout))
{
if (mWorkoutContext == null)
{
mWorkoutContext = new WorkoutContext (form);
}
else
{
if (workout != mWorkoutContext.WorkOut)
{
mWorkoutContext = new WorkoutContext (workout);
}
}
return mWorkoutContext ;
}
}
In concurrent environment, for each user it is creating an instance for WorkOutContext but not release the instance after the request process completion. To Overcome this issue modified the CreateContext method as follow
public class WorkoutContext {
protected WorkoutContext mWorkoutContext ;
protected WorkOut mWorkOut;
protected WorkoutContext(WorkOut workout)
{
mWorkOut= workout;
}
public static WorkoutContext CreateContext(WorkOut workout))
{
return new WorkoutContext(workout);
}
}
Is there any other way to implement to have only one instance of WorkoutContext for the same WorkOut instance.
Try something like this:
public class WorkoutContext {
protected WorkOut mWorkOut;
private static Dictionary<WorkOut, WorkoutContext> dic = new ...;
private static object lockObj = new object();
protected WorkoutContext(WorkOut workout)
{
mWorkOut= workout;
}
public static WorkoutContext CreateContext(WorkOut workout)
{
lock(lockObj) {
if (dic.ContainsKey(workout))
return dic[workout];
var wc = new WorkoutContext(workout)
dic.Add(workout, wc);
return wc;
}
}
}
I've created a method in a class and I want to access the streamreader sr1 from another method within the same class but I can't seem to get access to the method!
public void showSelectedFile()
{
StreamReader sr1 = new StreamReader(File.OpenRead(ReturnTxt));
ReturnContenctRD = sr1.ReadToEnd();
}
public void DisposeSR1()
{
}
Can anyone explain to me how to access/alter these methods from other functions?
sr1 is local to the showSelectedFile() method; it goes out of scope when the method returns. If you want to make it visible to the other method, you have to make it a member of your class:
StreamReader sr1;
public void showSelectedFile()
{
sr1 = new StreamReader(File.OpenRead(ReturnTxt))
ReturnContenctRD = sr1.ReadToEnd();
}
public void DisposeSR1()
{
}
If it's just a matter of disposing it properly, wrap it in a using statement:
public void showSelectedFile()
{
using (StreamReader sr1 = new StreamReader(File.OpenRead(ReturnTxt)))
{
ReturnContenctRD = sr1.ReadToEnd();
}
}
You need to store the StreamReader in a class member variable
e.g.
class YourClass
{
private StreamReader _sr1;
public void showSelectedFile()
{
_sr1 = new StreamReader(File.OpenRead(ReturnTxt));
ReturnContenctRD = _sr1.ReadToEnd();
}
public void DisposeSR1()
{
if(_sr1 != null)
_sr1.Dispose()
}
}