问题
I have an example code like this:
public class SimpleLogger
{
private static SimpleLogger logger;
private string path = null;
protected SimpleLogger(string path)
{
this.path = path;
}
public static SimpleLogger Instance(string path)
{
if (logger == null)
{
logger = new SimpleLogger(path);
}
return logger;
}
public static void Info(string info)
{
string path = $"{logger.path}{DateTime.Now.ToShortDateString()}_Info.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine($"{DateTime.Now} - {info}");
}
}
}
and when I call:
SimpleLogger.Instance("path").Info("info");
There's an error:
member cannot be accessed with an instance reference qualify it with a type name instead static method
But I DO use type name, don't I?
But when I call it like this:
SimpleLogger.Instance("path");
SimpleLogger.Info("info");
it actually does work fine.
To make it work inline I have to make Info method non-static and then inline call work also fine. Why is that? I don't understand the mechanism here. Can someone explain? Is it beacuse Instance method returns SimpleLogger object and then info requires to be non-static to be able to work on an instance rather than a type?
回答1:
In C#, instance methods can only be called on an instance, whereas static methods can only be called on a class/struct itself.
Why can't you chain Info
onto SimpleLogger.Instance()
?
Because SimpleLogger.Instance(...)
returns an instance of SimpleLogger
, and you are trying to call a static method on the returned value. The returned value is an instance of SimpleLogger
, so you can't call a static method on it.
By making Info
non-static, you enable it to be called on an instance. Therefore, you can call it on the return value of Instance()
.
One reason for your confusion might be that you don't see the instance of SimpleLogger
in your chain of methods, so to better illustrate the idea of chaining methods, this:
SimpleLogger.Instance("path").Info("info");
is equivalent to:
SimpleLogger logger = impleLogger.Instance("path");
logger.Info("info");
See the instance of SimpleLogger
now?
回答2:
Exactly as you wrote. You call static methods on the class, cannot call them on objects, and your Instance
method returns concrete object of the SimpleLogger
class. If you want chaining of the methods (ie. SimpleLogger.Instance("path").Info("info");
), you'll have to change Info(string info)
to non-static class. It makes more sense to have those methods be non-static, and make the class be Singleton
回答3:
When you're calling
SimpleLogger.Instance("path").Info("info");
the .Instance(...) is returning an instance of the SimpleLogger class. Calling .Info directly on that instance is causing this warning, because .Info(...) is defined as static.
You could rewrite .Info() like this:
public void Info(string info)
{
string path = $"{this.path}{DateTime.Now.ToShortDateString()}_Info.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine($"{DateTime.Now} - {info}");
}
}
In this way, you can call
SimpleLogger.Instance("path").Info("info");
without the warning, but you cannot call this anymore:
SimpleLogger.Info("info");
回答4:
You are calling a static method from its instance. As I see, perhaps you are trying to create a Logger class as singleton patterns. Then you just make Info(string info) method to a non-static method:
public class SimpleLogger
{
private static SimpleLogger logger;
private string path = null;
protected SimpleLogger(string path)
{
this.path = path;
}
public static SimpleLogger Instance(string path)
{
if (logger == null)
{
logger = new SimpleLogger(path);
}
return logger;
}
public void Info(string info)
{
string path = $"{logger.path}{DateTime.Now.ToShortDateString()}_Info.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine($"{DateTime.Now} - {info}");
}
}
}
来源:https://stackoverflow.com/questions/52163629/member-cannot-be-accessed-with-an-instance-reference-qualify-it-with-a-type-nam